1ad301491f714031e628cbdf6c08f7c0ad1b5356
[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 "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     int firstGlyphLeftOverflow = -1;
918
919     bool breakNBSP = style()->autoWrap() && style()->nbspMode() == SPACE;
920     bool breakAll = (style()->wordBreak() == BreakAllWordBreak || style()->wordBreak() == BreakWordBreak) && style()->autoWrap();
921
922     for (int i = 0; i < len; i++) {
923         UChar c = txt[i];
924
925         bool previousCharacterIsSpace = isSpace;
926
927         bool isNewline = false;
928         if (c == '\n') {
929             if (style()->preserveNewline()) {
930                 m_hasBreak = true;
931                 isNewline = true;
932                 isSpace = false;
933             } else
934                 isSpace = true;
935         } else if (c == '\t') {
936             if (!style()->collapseWhiteSpace()) {
937                 m_hasTab = true;
938                 isSpace = false;
939             } else
940                 isSpace = true;
941         } else
942             isSpace = c == ' ';
943
944         if ((isSpace || isNewline) && !i)
945             m_hasBeginWS = true;
946         if ((isSpace || isNewline) && i == len - 1)
947             m_hasEndWS = true;
948
949         if (!ignoringSpaces && style()->collapseWhiteSpace() && previousCharacterIsSpace && isSpace)
950             ignoringSpaces = true;
951
952         if (ignoringSpaces && !isSpace)
953             ignoringSpaces = false;
954
955         // Ignore spaces and soft hyphens
956         if (ignoringSpaces) {
957             ASSERT(lastWordBoundary == i);
958             lastWordBoundary++;
959             continue;
960         } else if (c == softHyphen) {
961             currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
962             if (firstGlyphLeftOverflow < 0)
963                 firstGlyphLeftOverflow = glyphOverflow.left;
964             lastWordBoundary = i + 1;
965             continue;
966         }
967
968         bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP);
969         bool betweenWords = true;
970         int j = i;
971         while (c != '\n' && !isSpaceAccordingToStyle(c, style()) && c != '\t' && c != softHyphen) {
972             j++;
973             if (j == len)
974                 break;
975             c = txt[j];
976             if (isBreakable(breakIterator, j, nextBreakable, breakNBSP))
977                 break;
978             if (breakAll) {
979                 betweenWords = false;
980                 break;
981             }
982         }
983
984         int wordLen = j - i;
985         if (wordLen) {
986             float w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
987             if (firstGlyphLeftOverflow < 0)
988                 firstGlyphLeftOverflow = glyphOverflow.left;
989             currMinWidth += w;
990             if (betweenWords) {
991                 if (lastWordBoundary == i)
992                     currMaxWidth += w;
993                 else
994                     currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
995                 lastWordBoundary = j;
996             }
997
998             bool isSpace = (j < len) && isSpaceAccordingToStyle(c, style());
999             bool isCollapsibleWhiteSpace = (j < len) && style()->isCollapsibleWhiteSpace(c);
1000             if (j < len && style()->autoWrap())
1001                 m_hasBreakableChar = true;
1002
1003             // Add in wordSpacing to our currMaxWidth, but not if this is the last word on a line or the
1004             // last word in the run.
1005             if (wordSpacing && (isSpace || isCollapsibleWhiteSpace) && !containsOnlyWhitespace(j, len-j))
1006                 currMaxWidth += wordSpacing;
1007
1008             if (firstWord) {
1009                 firstWord = false;
1010                 // If the first character in the run is breakable, then we consider ourselves to have a beginning
1011                 // minimum width of 0, since a break could occur right before our run starts, preventing us from ever
1012                 // being appended to a previous text run when considering the total minimum width of the containing block.
1013                 if (hasBreak)
1014                     m_hasBreakableChar = true;
1015                 m_beginMinWidth = hasBreak ? 0 : w;
1016             }
1017             m_endMinWidth = w;
1018
1019             if (currMinWidth > m_minWidth)
1020                 m_minWidth = currMinWidth;
1021             currMinWidth = 0;
1022
1023             i += wordLen - 1;
1024         } else {
1025             // Nowrap can never be broken, so don't bother setting the
1026             // breakable character boolean. Pre can only be broken if we encounter a newline.
1027             if (style()->autoWrap() || isNewline)
1028                 m_hasBreakableChar = true;
1029
1030             if (currMinWidth > m_minWidth)
1031                 m_minWidth = currMinWidth;
1032             currMinWidth = 0;
1033
1034             if (isNewline) { // Only set if preserveNewline was true and we saw a newline.
1035                 if (firstLine) {
1036                     firstLine = false;
1037                     leadWidth = 0;
1038                     if (!style()->autoWrap())
1039                         m_beginMinWidth = currMaxWidth;
1040                 }
1041
1042                 if (currMaxWidth > m_maxWidth)
1043                     m_maxWidth = currMaxWidth;
1044                 currMaxWidth = 0;
1045             } else {
1046                 TextRun run = RenderBlock::constructTextRun(this, f, txt + i, 1, style());
1047                 run.setCharactersLength(len - i);
1048                 ASSERT(run.charactersLength() >= run.length());
1049
1050                 run.setAllowTabs(allowTabs());
1051                 run.setXPos(leadWidth + currMaxWidth);
1052
1053                 currMaxWidth += f.width(run);
1054                 glyphOverflow.right = 0;
1055                 needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len - 1;
1056             }
1057             ASSERT(lastWordBoundary == i);
1058             lastWordBoundary++;
1059         }
1060     }
1061
1062     if (firstGlyphLeftOverflow > 0)
1063         glyphOverflow.left = firstGlyphLeftOverflow;
1064
1065     if ((needsWordSpacing && len > 1) || (ignoringSpaces && !firstWord))
1066         currMaxWidth += wordSpacing;
1067
1068     m_minWidth = max(currMinWidth, m_minWidth);
1069     m_maxWidth = max(currMaxWidth, m_maxWidth);
1070
1071     if (!style()->autoWrap())
1072         m_minWidth = m_maxWidth;
1073
1074     if (style()->whiteSpace() == PRE) {
1075         if (firstLine)
1076             m_beginMinWidth = m_maxWidth;
1077         m_endMinWidth = currMaxWidth;
1078     }
1079
1080     setPreferredLogicalWidthsDirty(false);
1081 }
1082
1083 bool RenderText::isAllCollapsibleWhitespace()
1084 {
1085     int length = textLength();
1086     const UChar* text = characters();
1087     for (int i = 0; i < length; i++) {
1088         if (!style()->isCollapsibleWhiteSpace(text[i]))
1089             return false;
1090     }
1091     return true;
1092 }
1093     
1094 bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const
1095 {
1096     ASSERT(m_text);
1097     StringImpl& text = *m_text.impl();
1098     unsigned currPos;
1099     for (currPos = from;
1100          currPos < from + len && (text[currPos] == '\n' || text[currPos] == ' ' || text[currPos] == '\t');
1101          currPos++) { }
1102     return currPos >= (from + len);
1103 }
1104
1105 FloatPoint RenderText::firstRunOrigin() const
1106 {
1107     return IntPoint(firstRunX(), firstRunY());
1108 }
1109
1110 float RenderText::firstRunX() const
1111 {
1112     return m_firstTextBox ? m_firstTextBox->x() : 0;
1113 }
1114
1115 float RenderText::firstRunY() const
1116 {
1117     return m_firstTextBox ? m_firstTextBox->y() : 0;
1118 }
1119     
1120 void RenderText::setSelectionState(SelectionState state)
1121 {
1122     InlineTextBox* box;
1123
1124     RenderObject::setSelectionState(state);
1125     if (state == SelectionStart || state == SelectionEnd || state == SelectionBoth) {
1126         int startPos, endPos;
1127         selectionStartEnd(startPos, endPos);
1128         if (selectionState() == SelectionStart) {
1129             endPos = textLength();
1130
1131             // to handle selection from end of text to end of line
1132             if (startPos != 0 && startPos == endPos)
1133                 startPos = endPos - 1;
1134         } else if (selectionState() == SelectionEnd)
1135             startPos = 0;
1136
1137         for (box = firstTextBox(); box; box = box->nextTextBox()) {
1138             if (box->isSelected(startPos, endPos)) {
1139                 RootInlineBox* line = box->root();
1140                 if (line)
1141                     line->setHasSelectedChildren(true);
1142             }
1143         }
1144     } else {
1145         for (box = firstTextBox(); box; box = box->nextTextBox()) {
1146             RootInlineBox* line = box->root();
1147             if (line)
1148                 line->setHasSelectedChildren(state == SelectionInside);
1149         }
1150     }
1151
1152     // The returned value can be null in case of an orphaned tree.
1153     if (RenderBlock* cb = containingBlock())
1154         cb->setSelectionState(state);
1155 }
1156
1157 void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset, unsigned len, bool force)
1158 {
1159     unsigned oldLen = textLength();
1160     unsigned newLen = text->length();
1161     int delta = newLen - oldLen;
1162     unsigned end = len ? offset + len - 1 : offset;
1163
1164     RootInlineBox* firstRootBox = 0;
1165     RootInlineBox* lastRootBox = 0;
1166
1167     bool dirtiedLines = false;
1168
1169     // Dirty all text boxes that include characters in between offset and offset+len.
1170     for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
1171         // Text run is entirely before the affected range.
1172         if (curr->end() < offset)
1173             continue;
1174
1175         // Text run is entirely after the affected range.
1176         if (curr->start() > end) {
1177             curr->offsetRun(delta);
1178             RootInlineBox* root = curr->root();
1179             if (!firstRootBox) {
1180                 firstRootBox = root;
1181                 if (!dirtiedLines) {
1182                     // The affected area was in between two runs. Go ahead and mark the root box of
1183                     // the run after the affected area as dirty.
1184                     firstRootBox->markDirty();
1185                     dirtiedLines = true;
1186                 }
1187             }
1188             lastRootBox = root;
1189         } else if (curr->end() >= offset && curr->end() <= end) {
1190             // Text run overlaps with the left end of the affected range.
1191             curr->dirtyLineBoxes();
1192             dirtiedLines = true;
1193         } else if (curr->start() <= offset && curr->end() >= end) {
1194             // Text run subsumes the affected range.
1195             curr->dirtyLineBoxes();
1196             dirtiedLines = true;
1197         } else if (curr->start() <= end && curr->end() >= end) {
1198             // Text run overlaps with right end of the affected range.
1199             curr->dirtyLineBoxes();
1200             dirtiedLines = true;
1201         }
1202     }
1203
1204     // Now we have to walk all of the clean lines and adjust their cached line break information
1205     // to reflect our updated offsets.
1206     if (lastRootBox)
1207         lastRootBox = lastRootBox->nextRootBox();
1208     if (firstRootBox) {
1209         RootInlineBox* prev = firstRootBox->prevRootBox();
1210         if (prev)
1211             firstRootBox = prev;
1212     } else if (lastTextBox()) {
1213         ASSERT(!lastRootBox);
1214         firstRootBox = lastTextBox()->root();
1215         firstRootBox->markDirty();
1216         dirtiedLines = true;
1217     }
1218     for (RootInlineBox* curr = firstRootBox; curr && curr != lastRootBox; curr = curr->nextRootBox()) {
1219         if (curr->lineBreakObj() == this && curr->lineBreakPos() > end)
1220             curr->setLineBreakPos(curr->lineBreakPos() + delta);
1221     }
1222
1223     // If the text node is empty, dirty the line where new text will be inserted.
1224     if (!firstTextBox() && parent()) {
1225         parent()->dirtyLinesFromChangedChild(this);
1226         dirtiedLines = true;
1227     }
1228
1229     m_linesDirty = dirtiedLines;
1230     setText(text, force);
1231 }
1232
1233 static inline bool isInlineFlowOrEmptyText(const RenderObject* o)
1234 {
1235     if (o->isRenderInline())
1236         return true;
1237     if (!o->isText())
1238         return false;
1239     StringImpl* text = toRenderText(o)->text();
1240     if (!text)
1241         return true;
1242     return !text->length();
1243 }
1244
1245 UChar RenderText::previousCharacter() const
1246 {
1247     // find previous text renderer if one exists
1248     const RenderObject* previousText = this;
1249     while ((previousText = previousText->previousInPreOrder()))
1250         if (!isInlineFlowOrEmptyText(previousText))
1251             break;
1252     UChar prev = ' ';
1253     if (previousText && previousText->isText())
1254         if (StringImpl* previousString = toRenderText(previousText)->text())
1255             prev = (*previousString)[previousString->length() - 1];
1256     return prev;
1257 }
1258
1259 void RenderText::transformText(String& text) const
1260 {
1261     ASSERT(style());
1262     switch (style()->textTransform()) {
1263     case TTNONE:
1264         break;
1265     case CAPITALIZE:
1266         makeCapitalized(&text, previousCharacter());
1267         break;
1268     case UPPERCASE:
1269         text.makeUpper();
1270         break;
1271     case LOWERCASE:
1272         text.makeLower();
1273         break;
1274     }
1275 }
1276
1277 void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
1278 {
1279     ASSERT(text);
1280     m_text = text;
1281     if (m_needsTranscoding) {
1282         const TextEncoding* encoding = document()->decoder() ? &document()->decoder()->encoding() : 0;
1283         fontTranscoder().convert(m_text, style()->font().fontDescription(), encoding);
1284     }
1285     ASSERT(m_text);
1286
1287     if (style()) {
1288         transformText(m_text);
1289
1290         // We use the same characters here as for list markers.
1291         // See the listMarkerText function in RenderListMarker.cpp.
1292         switch (style()->textSecurity()) {
1293         case TSNONE:
1294             break;
1295         case TSCIRCLE:
1296             secureText(whiteBullet);
1297             break;
1298         case TSDISC:
1299             secureText(bullet);
1300             break;
1301         case TSSQUARE:
1302             secureText(blackSquare);
1303         }
1304     }
1305
1306     ASSERT(m_text);
1307     ASSERT(!isBR() || (textLength() == 1 && m_text[0] == '\n'));
1308
1309     m_isAllASCII = m_text.containsOnlyASCII();
1310 }
1311
1312 void RenderText::secureText(UChar mask)
1313 {
1314     if (!m_text.length())
1315         return;
1316
1317     int lastTypedCharacterOffsetToReveal = -1;
1318     String revealedText;
1319     SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->get(this) : 0;
1320     if (secureTextTimer && secureTextTimer->isActive()) {
1321         lastTypedCharacterOffsetToReveal = secureTextTimer->lastTypedCharacterOffset();
1322         if (lastTypedCharacterOffsetToReveal >= 0)
1323             revealedText.append(m_text[lastTypedCharacterOffsetToReveal]);
1324     }
1325
1326     m_text.fill(mask);
1327     if (lastTypedCharacterOffsetToReveal >= 0) {
1328         m_text.replace(lastTypedCharacterOffsetToReveal, 1, revealedText);
1329         // m_text may be updated later before timer fires. We invalidate the lastTypedCharacterOffset to avoid inconsistency.
1330         secureTextTimer->invalidate();
1331     }
1332 }
1333
1334 void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
1335 {
1336     ASSERT(text);
1337
1338     if (!force && equal(m_text.impl(), text.get()))
1339         return;
1340
1341     setTextInternal(text);
1342     setNeedsLayoutAndPrefWidthsRecalc();
1343     m_knownToHaveNoOverflowAndNoFallbackFonts = false;
1344     
1345     AXObjectCache* axObjectCache = document()->axObjectCache();
1346     if (axObjectCache->accessibilityEnabled())
1347         axObjectCache->contentChanged(this);
1348 }
1349
1350 String RenderText::textWithoutTranscoding() const
1351 {
1352     // If m_text isn't transcoded or is secure, we can just return the modified text.
1353     if (!m_needsTranscoding || style()->textSecurity() != TSNONE)
1354         return text();
1355
1356     // Otherwise, we should use original text. If text-transform is
1357     // specified, we should transform the text on the fly.
1358     String text = originalText();
1359     if (style())
1360         transformText(text);
1361     return text;
1362 }
1363
1364 void RenderText::dirtyLineBoxes(bool fullLayout)
1365 {
1366     if (fullLayout)
1367         deleteTextBoxes();
1368     else if (!m_linesDirty) {
1369         for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
1370             box->dirtyLineBoxes();
1371     }
1372     m_linesDirty = false;
1373 }
1374
1375 InlineTextBox* RenderText::createTextBox()
1376 {
1377     return new (renderArena()) InlineTextBox(this);
1378 }
1379
1380 InlineTextBox* RenderText::createInlineTextBox()
1381 {
1382     InlineTextBox* textBox = createTextBox();
1383     if (!m_firstTextBox)
1384         m_firstTextBox = m_lastTextBox = textBox;
1385     else {
1386         m_lastTextBox->setNextTextBox(textBox);
1387         textBox->setPreviousTextBox(m_lastTextBox);
1388         m_lastTextBox = textBox;
1389     }
1390     textBox->setIsText(true);
1391     return textBox;
1392 }
1393
1394 void RenderText::positionLineBox(InlineBox* box)
1395 {
1396     InlineTextBox* s = toInlineTextBox(box);
1397
1398     // FIXME: should not be needed!!!
1399     if (!s->len()) {
1400         // We want the box to be destroyed.
1401         s->remove();
1402         if (m_firstTextBox == s)
1403             m_firstTextBox = s->nextTextBox();
1404         else
1405             s->prevTextBox()->setNextTextBox(s->nextTextBox());
1406         if (m_lastTextBox == s)
1407             m_lastTextBox = s->prevTextBox();
1408         else
1409             s->nextTextBox()->setPreviousTextBox(s->prevTextBox());
1410         s->destroy(renderArena());
1411         return;
1412     }
1413
1414     m_containsReversedText |= !s->isLeftToRightDirection();
1415 }
1416
1417 float RenderText::width(unsigned from, unsigned len, float xPos, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
1418 {
1419     if (from >= textLength())
1420         return 0;
1421
1422     if (from + len > textLength())
1423         len = textLength() - from;
1424
1425     return width(from, len, style(firstLine)->font(), xPos, fallbackFonts, glyphOverflow);
1426 }
1427
1428 float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
1429 {
1430     ASSERT(from + len <= textLength());
1431     if (!characters())
1432         return 0;
1433
1434     float w;
1435     if (&f == &style()->font()) {
1436         if (!style()->preserveNewline() && !from && len == textLength() && (!glyphOverflow || !glyphOverflow->computeBounds)) {
1437             if (fallbackFonts) {
1438                 ASSERT(glyphOverflow);
1439                 if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts) {
1440                     const_cast<RenderText*>(this)->computePreferredLogicalWidths(0, *fallbackFonts, *glyphOverflow);
1441                     if (fallbackFonts->isEmpty() && !glyphOverflow->left && !glyphOverflow->right && !glyphOverflow->top && !glyphOverflow->bottom)
1442                         m_knownToHaveNoOverflowAndNoFallbackFonts = true;
1443                 }
1444                 w = m_maxWidth;
1445             } else
1446                 w = maxLogicalWidth();
1447         } else
1448             w = widthFromCache(f, from, len, xPos, fallbackFonts, glyphOverflow);
1449     } else {
1450         TextRun run = RenderBlock::constructTextRun(const_cast<RenderText*>(this), f, text()->characters() + from, len, style());
1451         run.setCharactersLength(textLength() - from);
1452         ASSERT(run.charactersLength() >= run.length());
1453
1454         run.setAllowTabs(allowTabs());
1455         run.setXPos(xPos);
1456         w = f.width(run, fallbackFonts, glyphOverflow);
1457     }
1458
1459     return w;
1460 }
1461
1462 IntRect RenderText::linesBoundingBox() const
1463 {
1464     IntRect result;
1465     
1466     ASSERT(!firstTextBox() == !lastTextBox());  // Either both are null or both exist.
1467     if (firstTextBox() && lastTextBox()) {
1468         // Return the width of the minimal left side and the maximal right side.
1469         float logicalLeftSide = 0;
1470         float logicalRightSide = 0;
1471         for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
1472             if (curr == firstTextBox() || curr->logicalLeft() < logicalLeftSide)
1473                 logicalLeftSide = curr->logicalLeft();
1474             if (curr == firstTextBox() || curr->logicalRight() > logicalRightSide)
1475                 logicalRightSide = curr->logicalRight();
1476         }
1477         
1478         bool isHorizontal = style()->isHorizontalWritingMode();
1479         
1480         float x = isHorizontal ? logicalLeftSide : firstTextBox()->x();
1481         float y = isHorizontal ? firstTextBox()->y() : logicalLeftSide;
1482         float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastTextBox()->logicalBottom() - x;
1483         float height = isHorizontal ? lastTextBox()->logicalBottom() - y : logicalRightSide - logicalLeftSide;
1484         result = enclosingIntRect(FloatRect(x, y, width, height));
1485     }
1486
1487     return result;
1488 }
1489
1490 IntRect RenderText::linesVisualOverflowBoundingBox() const
1491 {
1492     if (!firstTextBox())
1493         return IntRect();
1494
1495     // Return the width of the minimal left side and the maximal right side.
1496     int logicalLeftSide = numeric_limits<int>::max();
1497     int logicalRightSide = numeric_limits<int>::min();
1498     for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
1499         logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow());
1500         logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow());
1501     }
1502     
1503     int logicalTop = firstTextBox()->logicalTopVisualOverflow();
1504     int logicalWidth = logicalRightSide - logicalLeftSide;
1505     int logicalHeight = lastTextBox()->logicalBottomVisualOverflow() - logicalTop;
1506     
1507     IntRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
1508     if (!style()->isHorizontalWritingMode())
1509         rect = rect.transposedRect();
1510     return rect;
1511 }
1512
1513 IntRect RenderText::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const
1514 {
1515     RenderObject* rendererToRepaint = containingBlock();
1516
1517     // Do not cross self-painting layer boundaries.
1518     RenderObject* enclosingLayerRenderer = enclosingLayer()->renderer();
1519     if (enclosingLayerRenderer != rendererToRepaint && !rendererToRepaint->isDescendantOf(enclosingLayerRenderer))
1520         rendererToRepaint = enclosingLayerRenderer;
1521
1522     // The renderer we chose to repaint may be an ancestor of repaintContainer, but we need to do a repaintContainer-relative repaint.
1523     if (repaintContainer && repaintContainer != rendererToRepaint && !rendererToRepaint->isDescendantOf(repaintContainer))
1524         return repaintContainer->clippedOverflowRectForRepaint(repaintContainer);
1525
1526     return rendererToRepaint->clippedOverflowRectForRepaint(repaintContainer);
1527 }
1528
1529 LayoutRect RenderText::selectionRectForRepaint(RenderBoxModelObject* repaintContainer, bool clipToVisibleContent)
1530 {
1531     ASSERT(!needsLayout());
1532
1533     if (selectionState() == SelectionNone)
1534         return LayoutRect();
1535     RenderBlock* cb = containingBlock();
1536     if (!cb)
1537         return LayoutRect();
1538
1539     // Now calculate startPos and endPos for painting selection.
1540     // We include a selection while endPos > 0
1541     LayoutUnit startPos, endPos;
1542     if (selectionState() == SelectionInside) {
1543         // We are fully selected.
1544         startPos = 0;
1545         endPos = textLength();
1546     } else {
1547         selectionStartEnd(startPos, endPos);
1548         if (selectionState() == SelectionStart)
1549             endPos = textLength();
1550         else if (selectionState() == SelectionEnd)
1551             startPos = 0;
1552     }
1553
1554     if (startPos == endPos)
1555         return IntRect();
1556
1557     LayoutRect rect;
1558     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
1559         rect.unite(box->localSelectionRect(startPos, endPos));
1560         rect.unite(ellipsisRectForBox(box, startPos, endPos));
1561     }
1562
1563     if (clipToVisibleContent)
1564         computeRectForRepaint(repaintContainer, rect);
1565     else {
1566         if (cb->hasColumns())
1567             cb->adjustRectForColumns(rect);
1568
1569         rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
1570     }
1571
1572     return rect;
1573 }
1574
1575 int RenderText::caretMinOffset() const
1576 {
1577     InlineTextBox* box = firstTextBox();
1578     if (!box)
1579         return 0;
1580     int minOffset = box->start();
1581     for (box = box->nextTextBox(); box; box = box->nextTextBox())
1582         minOffset = min<int>(minOffset, box->start());
1583     return minOffset;
1584 }
1585
1586 int RenderText::caretMaxOffset() const
1587 {
1588     InlineTextBox* box = lastTextBox();
1589     if (!box)
1590         return textLength();
1591     int maxOffset = box->start() + box->len();
1592     for (box = box->prevTextBox(); box; box = box->prevTextBox())
1593         maxOffset = max<int>(maxOffset, box->start() + box->len());
1594     return maxOffset;
1595 }
1596
1597 unsigned RenderText::caretMaxRenderedOffset() const
1598 {
1599     int l = 0;
1600     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
1601         l += box->len();
1602     return l;
1603 }
1604
1605 int RenderText::previousOffset(int current) const
1606 {
1607     StringImpl* si = m_text.impl();
1608     TextBreakIterator* iterator = cursorMovementIterator(si->characters(), si->length());
1609     if (!iterator)
1610         return current - 1;
1611
1612     long result = textBreakPreceding(iterator, current);
1613     if (result == TextBreakDone)
1614         result = current - 1;
1615
1616
1617     return result;
1618 }
1619
1620 #if PLATFORM(MAC)
1621
1622 #define HANGUL_CHOSEONG_START (0x1100)
1623 #define HANGUL_CHOSEONG_END (0x115F)
1624 #define HANGUL_JUNGSEONG_START (0x1160)
1625 #define HANGUL_JUNGSEONG_END (0x11A2)
1626 #define HANGUL_JONGSEONG_START (0x11A8)
1627 #define HANGUL_JONGSEONG_END (0x11F9)
1628 #define HANGUL_SYLLABLE_START (0xAC00)
1629 #define HANGUL_SYLLABLE_END (0xD7AF)
1630 #define HANGUL_JONGSEONG_COUNT (28)
1631
1632 enum HangulState {
1633     HangulStateL,
1634     HangulStateV,
1635     HangulStateT,
1636     HangulStateLV,
1637     HangulStateLVT,
1638     HangulStateBreak
1639 };
1640
1641 inline bool isHangulLVT(UChar32 character)
1642 {
1643     return (character - HANGUL_SYLLABLE_START) % HANGUL_JONGSEONG_COUNT;
1644 }
1645
1646 inline bool isMark(UChar32 c)
1647 {
1648     int8_t charType = u_charType(c);
1649     return charType == U_NON_SPACING_MARK || charType == U_ENCLOSING_MARK || charType == U_COMBINING_SPACING_MARK;
1650 }
1651
1652 inline bool isRegionalIndicator(UChar32 c)
1653 {
1654     // National flag emoji each consists of a pair of regional indicator symbols.
1655     return 0x1F1E6 <= c && c <= 0x1F1FF;
1656 }
1657
1658 #endif
1659
1660 int RenderText::previousOffsetForBackwardDeletion(int current) const
1661 {
1662 #if PLATFORM(MAC)
1663     ASSERT(m_text);
1664     StringImpl& text = *m_text.impl();
1665     UChar32 character;
1666     bool sawRegionalIndicator = false;
1667     while (current > 0) {
1668         if (U16_IS_TRAIL(text[--current]))
1669             --current;
1670         if (current < 0)
1671             break;
1672
1673         UChar32 character = text.characterStartingAt(current);
1674
1675         if (sawRegionalIndicator) {
1676             // We don't check if the pair of regional indicator symbols before current position can actually be combined
1677             // into a flag, and just delete it. This may not agree with how the pair is rendered in edge cases,
1678             // but is good enough in practice.
1679             if (isRegionalIndicator(character))
1680                 break;
1681             // Don't delete a preceding character that isn't a regional indicator symbol.
1682             U16_FWD_1_UNSAFE(text, current);
1683         }
1684
1685         // We don't combine characters in Armenian ... Limbu range for backward deletion.
1686         if ((character >= 0x0530) && (character < 0x1950))
1687             break;
1688
1689         if (isRegionalIndicator(character)) {
1690             sawRegionalIndicator = true;
1691             continue;
1692         }
1693
1694         if (!isMark(character) && (character != 0xFF9E) && (character != 0xFF9F))
1695             break;
1696     }
1697
1698     if (current <= 0)
1699         return current;
1700
1701     // Hangul
1702     character = text.characterStartingAt(current);
1703     if (((character >= HANGUL_CHOSEONG_START) && (character <= HANGUL_JONGSEONG_END)) || ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END))) {
1704         HangulState state;
1705         HangulState initialState;
1706
1707         if (character < HANGUL_JUNGSEONG_START)
1708             state = HangulStateL;
1709         else if (character < HANGUL_JONGSEONG_START)
1710             state = HangulStateV;
1711         else if (character < HANGUL_SYLLABLE_START)
1712             state = HangulStateT;
1713         else
1714             state = isHangulLVT(character) ? HangulStateLVT : HangulStateLV;
1715
1716         initialState = state;
1717
1718         while (current > 0 && ((character = text.characterStartingAt(current - 1)) >= HANGUL_CHOSEONG_START) && (character <= HANGUL_SYLLABLE_END) && ((character <= HANGUL_JONGSEONG_END) || (character >= HANGUL_SYLLABLE_START))) {
1719             switch (state) {
1720             case HangulStateV:
1721                 if (character <= HANGUL_CHOSEONG_END)
1722                     state = HangulStateL;
1723                 else if ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END) && !isHangulLVT(character))
1724                     state = HangulStateLV;
1725                 else if (character > HANGUL_JUNGSEONG_END)
1726                     state = HangulStateBreak;
1727                 break;
1728             case HangulStateT:
1729                 if ((character >= HANGUL_JUNGSEONG_START) && (character <= HANGUL_JUNGSEONG_END))
1730                     state = HangulStateV;
1731                 else if ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END))
1732                     state = (isHangulLVT(character) ? HangulStateLVT : HangulStateLV);
1733                 else if (character < HANGUL_JUNGSEONG_START)
1734                     state = HangulStateBreak;
1735                 break;
1736             default:
1737                 state = (character < HANGUL_JUNGSEONG_START) ? HangulStateL : HangulStateBreak;
1738                 break;
1739             }
1740             if (state == HangulStateBreak)
1741                 break;
1742
1743             --current;
1744         }
1745     }
1746
1747     return current;
1748 #else
1749     // Platforms other than Mac delete by one code point.
1750     return current - 1;
1751 #endif
1752 }
1753
1754 int RenderText::nextOffset(int current) const
1755 {
1756     StringImpl* si = m_text.impl();
1757     TextBreakIterator* iterator = cursorMovementIterator(si->characters(), si->length());
1758     if (!iterator)
1759         return current + 1;
1760
1761     long result = textBreakFollowing(iterator, current);
1762     if (result == TextBreakDone)
1763         result = current + 1;
1764
1765
1766     return result;
1767 }
1768
1769 #ifndef NDEBUG
1770
1771 void RenderText::checkConsistency() const
1772 {
1773 #ifdef CHECK_CONSISTENCY
1774     const InlineTextBox* prev = 0;
1775     for (const InlineTextBox* child = m_firstTextBox; child != 0; child = child->nextTextBox()) {
1776         ASSERT(child->renderer() == this);
1777         ASSERT(child->prevTextBox() == prev);
1778         prev = child;
1779     }
1780     ASSERT(prev == m_lastTextBox);
1781 #endif
1782 }
1783
1784 #endif
1785
1786 void RenderText::momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset)
1787 {
1788     if (!gSecureTextTimers)
1789         gSecureTextTimers = new SecureTextTimerMap;
1790
1791     SecureTextTimer* secureTextTimer = gSecureTextTimers->get(this);
1792     if (!secureTextTimer) {
1793         secureTextTimer = new SecureTextTimer(this);
1794         gSecureTextTimers->add(this, secureTextTimer);
1795     }
1796     secureTextTimer->restartWithNewText(lastTypedCharacterOffset);
1797 }
1798
1799 } // namespace WebCore