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