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