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