Changeset 32508 in webkit


Ignore:
Timestamp:
Apr 24, 2008 12:09:48 PM (16 years ago)
Author:
mitz@apple.com
Message:

WebCore:

Reviewed by Darin Adler.

The three main changes in this patch are:

1) Making all inline boxes know their bidi level, instead of just text

boxes knowing whether their bidi level is odd or even. This is
required for the next change.

2) Replacing RenderObject::inlineBox() with

Position::getInlineBoxAndOffset() in recognition of the fact that the
inline box containing the primary caret for a position in a given
node may belong to a different node's renderer.

3) Changing RenderObject::caretRect() to take an InlineBox parameter,

and changing callers to call VisiblePosition::caretRect(), which
locates the inline box, then calls caretRect() on the renderer for
that box. This, combined with the previous change, ensures that the
primary caret is rendered at the right place for positions that
lie on a directionality boundary.

Test: platform/mac/editing/input/caret-primary-bidi.html

  • WebCore.base.exp: Added the VisiblePosition(Node*, int, EAffinity) constructor and VisiblePosition::caretRect(), and sorted.
  • dom/Position.cpp: (WebCore::nextRenderedEditable): Adjusted for the removal of RenderObject::inlineBox(). (WebCore::previousRenderedEditable): Ditto. (WebCore::Position::rendersInDifferentPosition): Ditto. (WebCore::Position::getInlineBoxAndOffset): Added. Gets the inline box and the offset within that box at which the primary caret for this position should render.
  • dom/Position.h:
  • editing/DeleteSelectionCommand.cpp: (WebCore::DeleteSelectionCommand::mergeParagraphs): Changed to call VisiblePosition::caretRect() instead of calling the RenderObject method.
  • editing/SelectionController.cpp: (WebCore::caretY): Ditto. (WebCore::SelectionController::xPosForVerticalArrowNavigation): Ditto. (WebCore::SelectionController::layout): Ditto.
  • editing/VisiblePosition.cpp: (WebCore::VisiblePosition::caretRect): Changed to call getInlineBoxAndOffset() to get the correct inline box and call the renderer for that box.
  • editing/VisiblePosition.h: (WebCore::VisiblePosition::getInlineBoxAndOffset): Added convenience methods for getting the inline box and caret offset for a visible position, accounting for its affinity.
  • editing/visible_units.cpp: (WebCore::rootBoxForLine): Changed to use getInlineBoxAndOffset() instead of RenderObject::inlineBox(). (WebCore::startPositionForLine): (WebCore::endPositionForLine): (WebCore::previousLinePosition): Ditto. (WebCore::nextLinePosition): Ditto.
  • page/AccessibilityObject.cpp: (WebCore::updateAXLineStartForVisiblePosition): Ditto.
  • page/Frame.cpp: (WebCore::Frame::firstRectForRange): Ditto.
  • rendering/InlineBox.cpp: (WebCore::InlineBox::caretMinOffset): Changed to forward to the renderer. (WebCore::InlineBox::caretMaxOffset): Ditto.
  • rendering/InlineBox.h: Replaced the m_reversed bit, intended for use in InlineTextBox only, with six bits of the bidi level of the box, intended for use in all leaf inline boxes. (WebCore::InlineBox::InlineBox): Added missing initializer for m_dirOverride and initialized the bidi level. (WebCore::InlineBox::bidiLevel): Added this accessor. (WebCore::InlineBox::setBidiLevel): Ditto. (WebCore::InlineBox::direction): Ditto. (WebCore::InlineBox::caretLeftmostOffset): Added this convenience method. (WebCore::InlineBox::caretRightmostOffset): Ditto.
  • rendering/InlineTextBox.cpp: Replaced all references to m_reversed with checking of direction(). (WebCore::InlineTextBox::selectionRect): (WebCore::InlineTextBox::placeEllipsisBox): (WebCore::InlineTextBox::paint): (WebCore::InlineTextBox::paintSelection): (WebCore::InlineTextBox::paintCompositionBackground): (WebCore::InlineTextBox::paintSpellingOrGrammarMarker): (WebCore::InlineTextBox::paintTextMatchMarker): (WebCore::InlineTextBox::textPos): (WebCore::InlineTextBox::offsetForPosition): (WebCore::InlineTextBox::positionForOffset):
  • rendering/RenderBR.cpp: Removed inlineBox().
  • rendering/RenderBR.h: Ditto.
  • rendering/RenderBox.cpp: (WebCore::RenderBox::caretRect): Changed to take an inline box and account for the direction of the box (or the renderer) in positioning the caret: in right-to-left boxes, the "before" position is to the right while "after" is to the left.
  • rendering/RenderBox.h:
  • rendering/RenderFlow.cpp: (WebCore::RenderFlow::caretRect): Updated the signature.
  • rendering/RenderFlow.h:
  • rendering/RenderObject.cpp: (WebCore::RenderObject::caretRect): Updated the signature. (WebCore::RenderObject::caretMaxOffset): Changed to return the child node count (or 1 if there are no children) for replaced elements, such as <select>s.
  • rendering/RenderObject.h:
  • rendering/RenderReplaced.cpp: Removed caretMinOffset() and caretMaxOffset() because the base class implementation does the right thing for replaced objects now.
  • rendering/RenderReplaced.h:
  • rendering/RenderSVGInlineText.cpp: (WebCore::RenderSVGInlineText::caretRect): Updated the signature. (WebCore::RenderSVGInlineText::positionForCoordinates): Updated for the change from m_reversed to direction().
  • rendering/RenderSVGInlineText.h:
  • rendering/RenderText.cpp: (WebCore::RenderText::caretRect): Changed to take an inline box and removed the code that used to find the inline for the given position. Changed use of m_reversed to use direction(). (WebCore::RenderText::position): Changed use of m_reversed to use direction().
  • rendering/RenderText.h:
  • rendering/RenderTextControl.cpp: (WebCore::RenderTextControl::textWithHardLineBreaks): Adjusted for the removal of RenderObject::inlineBox().
  • rendering/RenderTreeAsText.cpp: (WebCore::writeTextRun): Changed to use direction() instead of m_reversed.
  • rendering/SVGInlineTextBox.cpp: Ditto. (WebCore::SVGInlineTextBox::calculateGlyphBoundaries): (WebCore::SVGInlineTextBoxClosestCharacterToPositionWalker::chunkPortionCallback): (WebCore::SVGInlineTextBox::svgCharacterHitsPosition):
  • rendering/SVGRenderTreeAsText.cpp: Ditto. (WebCore::writeSVGInlineTextBox):
  • rendering/SVGRootInlineBox.cpp: Ditto. (WebCore::svgTextRunForInlineTextBox): (WebCore::cummulatedWidthOrHeightOfTextChunk): (WebCore::SVGRootInlineBox::buildLayoutInformationForTextBox):
  • rendering/bidi.cpp: (WebCore::RenderBlock::constructLine): Made this function set the bidi level on all leaf boxes.
  • svg/SVGTextContentElement.cpp: Changed to use direction() instead of m_reversed. (WebCore::cumulativeCharacterRangeLength): (WebCore::SVGInlineTextBoxQueryWalker::chunkPortionCallback):

WebKit/mac:

Reviewed by Darin Adler.

  • WebView/WebFrame.mm: (-[WebFrame _caretRectAtNode:offset:affinity:]): Changed to use VisiblePosition::caretRect() instead of the RenderObject method which was removed.

LayoutTests:

Reviewed by Darin Adler.

  • test the visual position of the primary caret in bidirectional text
  • platform/mac/editing/input/caret-primary-bidi-expected.txt: Added.
  • platform/mac/editing/input/caret-primary-bidi.html: Added.
Location:
trunk
Files:
2 added
38 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r32497 r32508  
     12008-04-24  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Darin Adler.
     4
     5        - test the visual position of the primary caret in bidirectional text
     6
     7        * platform/mac/editing/input/caret-primary-bidi-expected.txt: Added.
     8        * platform/mac/editing/input/caret-primary-bidi.html: Added.
     9
    1102008-04-24  Justin Garcia  <justin.garcia@apple.com>
    211
  • trunk/WebCore/ChangeLog

    r32504 r32508  
     12008-04-24  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Darin Adler.
     4
     5        - preparation for https://bugs.webkit.org/show_bug.cgi?id=3729
     6          <rdar://problem/4036353> REGRESSION: arrow keys move insertion bar backwards in RTL text
     7
     8        The three main changes in this patch are:
     9
     10        1) Making all inline boxes know their bidi level, instead of just text
     11           boxes knowing whether their bidi level is odd or even. This is
     12           required for the next change.
     13
     14        2) Replacing RenderObject::inlineBox() with
     15           Position::getInlineBoxAndOffset() in recognition of the fact that the
     16           inline box containing the primary caret for a position in a given
     17           node may belong to a different node's renderer.
     18
     19        3) Changing RenderObject::caretRect() to take an InlineBox parameter,
     20           and changing callers to call VisiblePosition::caretRect(), which
     21           locates the inline box, then calls caretRect() on the renderer for
     22           that box. This, combined with the previous change, ensures that the
     23           primary caret is rendered at the right place for positions that
     24           lie on a directionality boundary.
     25
     26        Test: platform/mac/editing/input/caret-primary-bidi.html
     27
     28        * WebCore.base.exp: Added the VisiblePosition(Node*, int, EAffinity)
     29        constructor and VisiblePosition::caretRect(), and sorted.
     30
     31        * dom/Position.cpp:
     32        (WebCore::nextRenderedEditable): Adjusted for the removal of
     33        RenderObject::inlineBox().
     34        (WebCore::previousRenderedEditable): Ditto.
     35        (WebCore::Position::rendersInDifferentPosition): Ditto.
     36        (WebCore::Position::getInlineBoxAndOffset): Added. Gets the inline box
     37        and the offset within that box at which the primary caret for this
     38        position should render.
     39
     40        * dom/Position.h:
     41
     42        * editing/DeleteSelectionCommand.cpp:
     43        (WebCore::DeleteSelectionCommand::mergeParagraphs): Changed to call
     44        VisiblePosition::caretRect() instead of calling the RenderObject method.
     45
     46        * editing/SelectionController.cpp:
     47        (WebCore::caretY): Ditto.
     48        (WebCore::SelectionController::xPosForVerticalArrowNavigation): Ditto.
     49        (WebCore::SelectionController::layout): Ditto.
     50
     51        * editing/VisiblePosition.cpp:
     52        (WebCore::VisiblePosition::caretRect): Changed to call
     53        getInlineBoxAndOffset() to get the correct inline box and call the
     54        renderer for that box.
     55
     56        * editing/VisiblePosition.h:
     57        (WebCore::VisiblePosition::getInlineBoxAndOffset): Added convenience
     58        methods for getting the inline box and caret offset for a visible
     59        position, accounting for its affinity.
     60
     61        * editing/visible_units.cpp:
     62        (WebCore::rootBoxForLine): Changed to use getInlineBoxAndOffset()
     63        instead of RenderObject::inlineBox().
     64        (WebCore::startPositionForLine):
     65        (WebCore::endPositionForLine):
     66        (WebCore::previousLinePosition): Ditto.
     67        (WebCore::nextLinePosition): Ditto.
     68
     69        * page/AccessibilityObject.cpp:
     70        (WebCore::updateAXLineStartForVisiblePosition): Ditto.
     71
     72        * page/Frame.cpp:
     73        (WebCore::Frame::firstRectForRange): Ditto.
     74
     75        * rendering/InlineBox.cpp:
     76        (WebCore::InlineBox::caretMinOffset): Changed to forward to the
     77        renderer.
     78        (WebCore::InlineBox::caretMaxOffset): Ditto.
     79        * rendering/InlineBox.h: Replaced the m_reversed bit, intended for use
     80        in InlineTextBox only, with six bits of the bidi level of the box,
     81        intended for use in all leaf inline boxes.
     82        (WebCore::InlineBox::InlineBox): Added missing initializer for
     83        m_dirOverride and initialized the bidi level.
     84        (WebCore::InlineBox::bidiLevel): Added this accessor.
     85        (WebCore::InlineBox::setBidiLevel): Ditto.
     86        (WebCore::InlineBox::direction): Ditto.
     87        (WebCore::InlineBox::caretLeftmostOffset): Added this convenience
     88        method.
     89        (WebCore::InlineBox::caretRightmostOffset): Ditto.
     90
     91        * rendering/InlineTextBox.cpp: Replaced all references to m_reversed
     92        with checking of direction().
     93        (WebCore::InlineTextBox::selectionRect):
     94        (WebCore::InlineTextBox::placeEllipsisBox):
     95        (WebCore::InlineTextBox::paint):
     96        (WebCore::InlineTextBox::paintSelection):
     97        (WebCore::InlineTextBox::paintCompositionBackground):
     98        (WebCore::InlineTextBox::paintSpellingOrGrammarMarker):
     99        (WebCore::InlineTextBox::paintTextMatchMarker):
     100        (WebCore::InlineTextBox::textPos):
     101        (WebCore::InlineTextBox::offsetForPosition):
     102        (WebCore::InlineTextBox::positionForOffset):
     103
     104        * rendering/RenderBR.cpp: Removed inlineBox().
     105        * rendering/RenderBR.h: Ditto.
     106
     107        * rendering/RenderBox.cpp:
     108        (WebCore::RenderBox::caretRect): Changed to take an inline box and
     109        account for the direction of the box (or the renderer) in positioning
     110        the caret: in right-to-left boxes, the "before" position is to the right
     111        while "after" is to the left.
     112        * rendering/RenderBox.h:
     113
     114        * rendering/RenderFlow.cpp:
     115        (WebCore::RenderFlow::caretRect): Updated the signature.
     116        * rendering/RenderFlow.h:
     117
     118        * rendering/RenderObject.cpp:
     119        (WebCore::RenderObject::caretRect): Updated the signature.
     120        (WebCore::RenderObject::caretMaxOffset): Changed to return the child
     121        node count (or 1 if there are no children) for replaced elements, such
     122        as <select>s.
     123        * rendering/RenderObject.h:
     124
     125        * rendering/RenderReplaced.cpp: Removed caretMinOffset() and
     126        caretMaxOffset() because the base class implementation does the right
     127        thing for replaced objects now.
     128        * rendering/RenderReplaced.h:
     129
     130        * rendering/RenderSVGInlineText.cpp:
     131        (WebCore::RenderSVGInlineText::caretRect): Updated the signature.
     132        (WebCore::RenderSVGInlineText::positionForCoordinates): Updated for
     133        the change from m_reversed to direction().
     134        * rendering/RenderSVGInlineText.h:
     135
     136        * rendering/RenderText.cpp:
     137        (WebCore::RenderText::caretRect): Changed to take an inline box and
     138        removed the code that used to find the inline for the given position.
     139        Changed use of m_reversed to use direction().
     140        (WebCore::RenderText::position): Changed use of m_reversed to use
     141        direction().
     142        * rendering/RenderText.h:
     143
     144        * rendering/RenderTextControl.cpp:
     145        (WebCore::RenderTextControl::textWithHardLineBreaks): Adjusted for the
     146        removal of RenderObject::inlineBox().
     147
     148        * rendering/RenderTreeAsText.cpp:
     149        (WebCore::writeTextRun): Changed to use direction() instead of
     150        m_reversed.
     151
     152        * rendering/SVGInlineTextBox.cpp: Ditto.
     153        (WebCore::SVGInlineTextBox::calculateGlyphBoundaries):
     154        (WebCore::SVGInlineTextBoxClosestCharacterToPositionWalker::chunkPortionCallback):
     155        (WebCore::SVGInlineTextBox::svgCharacterHitsPosition):
     156
     157        * rendering/SVGRenderTreeAsText.cpp: Ditto.
     158        (WebCore::writeSVGInlineTextBox):
     159
     160        * rendering/SVGRootInlineBox.cpp: Ditto.
     161        (WebCore::svgTextRunForInlineTextBox):
     162        (WebCore::cummulatedWidthOrHeightOfTextChunk):
     163        (WebCore::SVGRootInlineBox::buildLayoutInformationForTextBox):
     164
     165        * rendering/bidi.cpp:
     166        (WebCore::RenderBlock::constructLine): Made this function set the
     167        bidi level on all leaf boxes.
     168
     169        * svg/SVGTextContentElement.cpp: Changed to use direction() instead of
     170        m_reversed.
     171        (WebCore::cumulativeCharacterRangeLength):
     172        (WebCore::SVGInlineTextBoxQueryWalker::chunkPortionCallback):
     173
    11742008-04-24  Sam Weinig  <sam@webkit.org>
    2175
  • trunk/WebCore/WebCore.base.exp

    r32320 r32508  
    335335__ZN7WebCore15StringTruncator14centerTruncateERKNS_6StringEfRKNS_4FontEb
    336336__ZN7WebCore15StringTruncator5widthERKNS_6StringERKNS_4FontEb
     337__ZN7WebCore15VisiblePositionC1EPNS_4NodeEiNS_9EAffinityE
    337338__ZN7WebCore15VisiblePositionC1ERKNS_8PositionENS_9EAffinityE
    338339__ZN7WebCore16FontPlatformDataC1EP6NSFontbb
     
    633634__ZNK7WebCore11FrameLoader16responseMIMETypeEv
    634635__ZNK7WebCore11FrameLoader20activeDocumentLoaderEv
     636__ZNK7WebCore11FrameLoader21isQuickRedirectComingEv
    635637__ZNK7WebCore11FrameLoader25provisionalDocumentLoaderEv
    636 __ZNK7WebCore11FrameLoader21isQuickRedirectComingEv
    637638__ZNK7WebCore11FrameLoader27numPendingOrLoadingRequestsEb
    638639__ZNK7WebCore11FrameLoader6clientEv
     
    702703__ZNK7WebCore15VisiblePosition4nextEb
    703704__ZNK7WebCore15VisiblePosition8previousEb
     705__ZNK7WebCore15VisiblePosition9caretRectEv
    704706__ZNK7WebCore16ResourceResponse13nsURLResponseEv
    705707__ZNK7WebCore17ResourceErrorBase8lazyInitEv
  • trunk/WebCore/dom/Position.cpp

    r32438 r32508  
    5151        if (!node)
    5252            return 0;
    53         if (!node->renderer())
     53        RenderObject* renderer = node->renderer();
     54        if (!renderer)
    5455            continue;
    55         if (node->renderer()->inlineBox(0))
     56        if (renderer->inlineBoxWrapper() || renderer->isText() && static_cast<RenderText*>(renderer)->firstTextBox())
    5657            return node;
    5758    }
     
    6566        if (!node)
    6667            return 0;
    67         if (!node->renderer())
     68        RenderObject* renderer = node->renderer();
     69        if (!renderer)
    6870            continue;
    69         if (node->renderer()->inlineBox(0))
     71        if (renderer->inlineBoxWrapper() || renderer->isText() && static_cast<RenderText*>(renderer)->firstTextBox())
    7072            return node;
    7173    }
     
    684686        return false;
    685687
    686     LOG(Editing, "renderer:               %p [%p]\n", renderer, renderer ? renderer->inlineBox(offset()) : 0);
     688    int ignoredCaretOffset;
     689    InlineBox* b1;
     690    getInlineBoxAndOffset(DOWNSTREAM, b1, ignoredCaretOffset);
     691    InlineBox* b2;
     692    pos.getInlineBoxAndOffset(DOWNSTREAM, b2, ignoredCaretOffset);
     693
     694    LOG(Editing, "renderer:               %p [%p]\n", renderer, b1);
    687695    LOG(Editing, "thisRenderedOffset:         %d\n", thisRenderedOffset);
    688     LOG(Editing, "posRenderer:            %p [%p]\n", posRenderer, posRenderer ? posRenderer->inlineBox(offset()) : 0);
     696    LOG(Editing, "posRenderer:            %p [%p]\n", posRenderer, b2);
    689697    LOG(Editing, "posRenderedOffset:      %d\n", posRenderedOffset);
    690698    LOG(Editing, "node min/max:           %d:%d\n", caretMinOffset(node()), caretMaxRenderedOffset(node()));
    691699    LOG(Editing, "pos node min/max:       %d:%d\n", caretMinOffset(pos.node()), caretMaxRenderedOffset(pos.node()));
    692700    LOG(Editing, "----------------------------------------------------------------------\n");
    693 
    694     InlineBox *b1 = renderer ? renderer->inlineBox(offset()) : 0;
    695     InlineBox *b2 = posRenderer ? posRenderer->inlineBox(pos.offset()) : 0;
    696701
    697702    if (!b1 || !b2) {
     
    753758   
    754759    return Position();
     760}
     761
     762void Position::getInlineBoxAndOffset(EAffinity affinity, InlineBox*& inlineBox, int& caretOffset) const
     763{
     764    TextDirection primaryDirection = LTR;
     765    for (RenderObject* r = node()->renderer(); r; r = r->parent()) {
     766        if (r->isBlockFlow()) {
     767            primaryDirection = r->style()->direction();
     768            break;
     769        }
     770    }
     771    getInlineBoxAndOffset(affinity, primaryDirection, inlineBox, caretOffset);
     772}
     773
     774void Position::getInlineBoxAndOffset(EAffinity affinity, TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const
     775{
     776    caretOffset = offset();
     777    RenderObject* renderer = node()->renderer();
     778    if (!renderer->isText()) {
     779        inlineBox = renderer->inlineBoxWrapper();
     780        if (!inlineBox || caretOffset > inlineBox->caretMinOffset() && caretOffset < inlineBox->caretMaxOffset())
     781            return;
     782    } else {
     783        RenderText* textRenderer = static_cast<RenderText*>(renderer);
     784
     785        InlineTextBox* box;
     786        InlineTextBox* candidate = 0;
     787
     788        for (box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
     789            int caretMinOffset = box->caretMinOffset();
     790            int caretMaxOffset = box->caretMaxOffset();
     791
     792            if (caretOffset < caretMinOffset || caretOffset > caretMaxOffset)
     793                continue;
     794
     795            if (caretOffset > caretMinOffset && caretOffset < caretMaxOffset) {
     796                inlineBox = box;
     797                return;
     798            }
     799
     800            if (caretOffset == caretMinOffset ^ affinity == UPSTREAM)
     801                break;
     802
     803            candidate = box;
     804        }
     805        inlineBox = box ? box : candidate;
     806    }
     807
     808    if (!inlineBox)
     809        return;
     810
     811    unsigned char level = inlineBox->bidiLevel();
     812
     813    if (inlineBox->direction() == primaryDirection) {
     814        if (caretOffset == inlineBox->caretRightmostOffset()) {
     815            InlineBox* nextBox = inlineBox->nextLeafChild();
     816            if (!nextBox || nextBox->bidiLevel() >= level)
     817                return;
     818
     819            level = nextBox->bidiLevel();
     820            InlineBox* prevBox = inlineBox;
     821            do {
     822                prevBox = prevBox->prevLeafChild();
     823            } while (prevBox && prevBox->bidiLevel() > level);
     824
     825            if (prevBox && prevBox->bidiLevel() == level)   // For example, abc FED 123 ^ CBA
     826                return;
     827
     828            // For example, abc 123 ^ CBA
     829            while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
     830                if (nextBox->bidiLevel() < level)
     831                    break;
     832                inlineBox = nextBox;
     833            }
     834            caretOffset = inlineBox->caretRightmostOffset();
     835        } else {
     836            InlineBox* prevBox = inlineBox->prevLeafChild();
     837            if (!prevBox || prevBox->bidiLevel() >= level)
     838                return;
     839
     840            level = prevBox->bidiLevel();
     841            InlineBox* nextBox = inlineBox;
     842            do {
     843                nextBox = nextBox->nextLeafChild();
     844            } while (nextBox && nextBox->bidiLevel() > level);
     845
     846            if (nextBox && nextBox->bidiLevel() == level)
     847                return;
     848
     849            while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
     850                if (prevBox->bidiLevel() < level)
     851                    break;
     852                inlineBox = prevBox;
     853            }
     854            caretOffset = inlineBox->caretLeftmostOffset();
     855        }
     856        return;
     857    }
     858
     859    if (caretOffset == inlineBox->caretLeftmostOffset()) {
     860        InlineBox* prevBox = inlineBox->prevLeafChild();
     861        if (!prevBox || prevBox->bidiLevel() < level) {
     862            // Left edge of a secondary run. Set to the right edge of the entire run.
     863            while (InlineBox* nextBox = inlineBox->nextLeafChild()) {
     864                if (nextBox->bidiLevel() < level)
     865                    break;
     866                inlineBox = nextBox;
     867            }
     868            caretOffset = inlineBox->caretRightmostOffset();
     869        } else if (prevBox->bidiLevel() > level) {
     870            // Right edge of a "tertiary" run. Set to the left edge of that run.
     871            while (InlineBox* tertiaryBox = inlineBox->prevLeafChild()) {
     872                if (tertiaryBox->bidiLevel() <= level)
     873                    break;
     874                inlineBox = tertiaryBox;
     875            }
     876            caretOffset = !inlineBox->caretLeftmostOffset();
     877        }
     878    } else {
     879        InlineBox* nextBox = inlineBox->nextLeafChild();
     880        if (!nextBox || nextBox->bidiLevel() < level) {
     881            // Right edge of a secondary run. Set to the left edge of the entire run.
     882            while (InlineBox* prevBox = inlineBox->prevLeafChild()) {
     883                if (prevBox->bidiLevel() < level)
     884                    break;
     885                inlineBox = prevBox;
     886            }
     887            caretOffset = inlineBox->caretLeftmostOffset();
     888        } else if (nextBox->bidiLevel() > level) {
     889            // Left edge of a "tertiary" run. Set to the right edge of that run.
     890            while (InlineBox* tertiaryBox = inlineBox->nextLeafChild()) {
     891                if (tertiaryBox->bidiLevel() <= level)
     892                    break;
     893                inlineBox = tertiaryBox;
     894            }
     895            caretOffset = inlineBox->caretRightmostOffset();
     896        }
     897    }
    755898}
    756899
  • trunk/WebCore/dom/Position.h

    r31161 r32508  
    2828
    2929#include "TextAffinity.h"
     30#include "TextDirection.h"
    3031#include <wtf/PassRefPtr.h>
    3132#include <wtf/RefPtr.h>
     
    3536class CSSComputedStyleDeclaration;
    3637class Element;
     38class InlineBox;
    3739class Node;
    3840class Range;
     
    8991    bool isRenderedCharacter() const;
    9092    bool rendersInDifferentPosition(const Position&) const;
    91    
     93
     94    void getInlineBoxAndOffset(EAffinity, InlineBox*&, int& caretOffset) const;
     95    void getInlineBoxAndOffset(EAffinity, TextDirection primaryDirection, InlineBox*&, int& caretOffset) const;
     96
    9297    static bool hasRenderedNonAnonymousDescendantsWithHeight(RenderObject*);
    9398    static bool nodeIsUserSelectNone(Node*);
  • trunk/WebCore/editing/DeleteSelectionCommand.cpp

    r30973 r32508  
    552552    // FIXME: Consider RTL.
    553553    // FIXME: handleSpecialCaseBRDelete prevents us from getting here in a case like <ul><li>foo<br><br></li></ul>^foo
    554     if (isStartOfParagraph(mergeDestination) &&
    555         startOfParagraphToMove.deepEquivalent().node()->renderer()->caretRect(startOfParagraphToMove.deepEquivalent().offset()).location().x() >
    556         mergeDestination.deepEquivalent().node()->renderer()->caretRect(startOfParagraphToMove.deepEquivalent().offset()).location().x()) {
     554    if (isStartOfParagraph(mergeDestination) && startOfParagraphToMove.caretRect().x() > mergeDestination.caretRect().x()) {
    557555        ASSERT(mergeDestination.deepEquivalent().downstream().node()->hasTagName(brTag));
    558556        removeNodeAndPruneAncestors(mergeDestination.deepEquivalent().downstream().node());
  • trunk/WebCore/editing/SelectionController.cpp

    r30564 r32508  
    496496static bool caretY(const VisiblePosition &c, int &y)
    497497{
    498     Position p = c.deepEquivalent();
    499     Node *n = p.node();
    500     if (!n)
    501         return false;
    502     RenderObject *r = p.node()->renderer();
    503     if (!r)
    504         return false;
    505     IntRect rect = r->caretRect(p.offset());
     498    IntRect rect = c.caretRect();
    506499    if (rect.isEmpty())
    507500        return false;
     
    628621       
    629622    if (m_xPosForVerticalArrowNavigation == NoXPosForVerticalArrowNavigation) {
    630         pos = VisiblePosition(pos, m_sel.affinity()).deepEquivalent();
     623        VisiblePosition visiblePosition(pos, m_sel.affinity());
    631624        // VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden
    632625        // after the selection is created and before this function is called.
    633         x = pos.isNotNull() ? pos.node()->renderer()->caretRect(pos.offset(), m_sel.affinity()).x() : 0;
     626        x = visiblePosition.isNotNull() ? visiblePosition.caretRect().x() : 0;
    634627        m_xPosForVerticalArrowNavigation = x;
    635628    }
     
    684677       
    685678    if (isCaret()) {
    686         Position pos = m_sel.start();
    687         pos = VisiblePosition(m_sel.start(), m_sel.affinity()).deepEquivalent();
     679        VisiblePosition pos(m_sel.start(), m_sel.affinity());
    688680        if (pos.isNotNull()) {
    689             ASSERT(pos.node()->renderer());
    690             m_caretRect = pos.node()->renderer()->caretRect(pos.offset(), m_sel.affinity());
    691            
     681            ASSERT(pos.deepEquivalent().node()->renderer());
     682            m_caretRect = pos.caretRect();
     683
    692684            int x, y;
    693             pos.node()->renderer()->absolutePositionForContent(x, y);
     685            pos.deepEquivalent().node()->renderer()->absolutePositionForContent(x, y);
    694686            m_caretPositionOnLayout = IntPoint(x, y);
    695687        }
  • trunk/WebCore/editing/VisiblePosition.cpp

    r30973 r32508  
    243243IntRect VisiblePosition::caretRect() const
    244244{
    245     if (!m_deepPosition.node() || !m_deepPosition.node()->renderer())
     245    Node* node = m_deepPosition.node();
     246    if (!node)
    246247        return IntRect();
    247248
    248     return m_deepPosition.node()->renderer()->caretRect(m_deepPosition.offset(), m_affinity);
     249    RenderObject* renderer = node->renderer();
     250    if (!renderer)
     251        return IntRect();
     252
     253    InlineBox* inlineBox;
     254    int caretOffset;
     255    getInlineBoxAndOffset(inlineBox, caretOffset);
     256
     257    if (inlineBox)
     258        renderer = inlineBox->object();
     259
     260    return renderer->caretRect(inlineBox, caretOffset);
    249261}
    250262
  • trunk/WebCore/editing/VisiblePosition.h

    r30973 r32508  
    2929#include "Node.h"
    3030#include "Position.h"
     31#include "TextDirection.h"
    3132
    3233namespace WebCore {
     
    4445// position is not at a line break.
    4546#define VP_UPSTREAM_IF_POSSIBLE UPSTREAM
     47
     48class InlineBox;
    4649
    4750class VisiblePosition {
     
    7578    Element* rootEditableElement() const { return m_deepPosition.isNotNull() ? m_deepPosition.node()->rootEditableElement() : 0; }
    7679   
     80    void getInlineBoxAndOffset(InlineBox*& inlineBox, int& caretOffset) const
     81    {
     82        m_deepPosition.getInlineBoxAndOffset(m_affinity, inlineBox, caretOffset);
     83    }
     84
     85    void getInlineBoxAndOffset(TextDirection primaryDirection, InlineBox*& inlineBox, int& caretOffset) const
     86    {
     87        m_deepPosition.getInlineBoxAndOffset(m_affinity, primaryDirection, inlineBox, caretOffset);
     88    }
     89
    7790    IntRect caretRect() const;
    7891
     
    8598    void init(const Position&, EAffinity);
    8699    Position canonicalPosition(const Position&);
    87        
     100
    88101    Position m_deepPosition;
    89102    EAffinity m_affinity;
  • trunk/WebCore/editing/visible_units.cpp

    r30973 r32508  
    258258    if (!renderer)
    259259        return 0;
    260    
    261     InlineBox *box = renderer->inlineBox(p.offset(), c.affinity());
    262     if (!box)
    263         return 0;
    264    
    265     return box->root();
     260
     261    InlineBox* box;
     262    int offset;
     263    c.getInlineBoxAndOffset(box, offset);
     264   
     265    return box ? box->root() : 0;
    266266}
    267267
     
    280280    if (c.isNull())
    281281        return VisiblePosition();
    282        
     282
    283283    RootInlineBox *rootBox = rootBoxForLine(c);
    284284    if (!rootBox) {
     
    348348    if (c.isNull())
    349349        return VisiblePosition();
    350        
     350
    351351    RootInlineBox *rootBox = rootBoxForLine(c);
    352352    if (!rootBox) {
     
    442442    RenderBlock *containingBlock = 0;
    443443    RootInlineBox *root = 0;
    444     InlineBox *box = renderer->inlineBox(p.offset(), visiblePosition.affinity());
     444    InlineBox* box;
     445    int ignoredCaretOffset;
     446    visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
    445447    if (box) {
    446448        root = box->root()->prevRootBox();
     
    463465            if (pos.isCandidate()) {
    464466                ASSERT(n->renderer());
    465                 box = n->renderer()->inlineBox(caretMaxOffset(n));
     467                Position maxPos(n, caretMaxOffset(n));
     468                maxPos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset);
    466469                if (box) {
    467470                    // previous root line box found
     
    512515    RenderBlock *containingBlock = 0;
    513516    RootInlineBox *root = 0;
    514     InlineBox *box = renderer->inlineBox(p.offset(), visiblePosition.affinity());
     517    InlineBox* box;
     518    int ignoredCaretOffset;
     519    visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
    515520    if (box) {
    516521        root = box->root()->nextRootBox();
     
    533538            if (pos.isCandidate()) {
    534539                ASSERT(n->renderer());
    535                 box = n->renderer()->inlineBox(caretMinOffset(n));
     540                pos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset);
    536541                if (box) {
    537542                    // next root line box found
  • trunk/WebCore/page/AccessibilityObject.cpp

    r32474 r32508  
    992992            break;
    993993        renderer = p.node()->renderer();
    994         if (!renderer || renderer->inlineBox(p.offset(), tempPosition.affinity()) || (renderer->isRenderBlock() && p.offset() == 0))
     994        if (!renderer || renderer->isRenderBlock() && !p.offset())
     995            break;
     996        InlineBox* box;
     997        int ignoredCaretOffset;
     998        p.getInlineBoxAndOffset(tempPosition.affinity(), box, ignoredCaretOffset);
     999        if (box)
    9951000            break;
    9961001        startPosition = tempPosition;
  • trunk/WebCore/page/Frame.cpp

    r32422 r32508  
    279279    ASSERT(range->startContainer(ec));
    280280    ASSERT(range->endContainer(ec));
    281     IntRect startCaretRect = range->startContainer(ec)->renderer()->caretRect(range->startOffset(ec), DOWNSTREAM, &extraWidthToEndOfLine);
    282     ASSERT(!ec);
    283     IntRect endCaretRect = range->endContainer(ec)->renderer()->caretRect(range->endOffset(ec), UPSTREAM);
    284     ASSERT(!ec);
    285    
     281    InlineBox* startInlineBox;
     282    int startCaretOffset;
     283    range->startPosition().getInlineBoxAndOffset(DOWNSTREAM, startInlineBox, startCaretOffset);
     284    IntRect startCaretRect = range->startContainer(ec)->renderer()->caretRect(startInlineBox, startCaretOffset, &extraWidthToEndOfLine);
     285
     286    InlineBox* endInlineBox;
     287    int endCaretOffset;
     288    range->endPosition().getInlineBoxAndOffset(UPSTREAM, endInlineBox, endCaretOffset);
     289    IntRect endCaretRect = range->endContainer(ec)->renderer()->caretRect(endInlineBox, endCaretOffset);
     290
    286291    if (startCaretRect.y() == endCaretRect.y()) {
    287292        // start and end are on the same line
  • trunk/WebCore/rendering/InlineBox.cpp

    r31200 r32508  
    8787int InlineBox::caretMinOffset() const
    8888{
    89     return 0;
     89    return m_object->caretMinOffset();
    9090}
    9191
    9292int InlineBox::caretMaxOffset() const
    9393{
    94     return 1;
     94    return m_object->caretMaxOffset();
    9595}
    9696
  • trunk/WebCore/rendering/InlineBox.h

    r28962 r32508  
    2323
    2424#include "RenderObject.h" // needed for RenderObject::PaintInfo
     25#include "TextDirection.h"
    2526
    2627namespace WebCore {
     
    4748        , m_firstLine(false)
    4849        , m_constructed(false)
     50        , m_bidiEmbeddingLevel(0)
    4951        , m_dirty(false)
    5052        , m_extracted(false)
     
    5557        , m_hasSelectedChildren(false)
    5658        , m_hasEllipsisBox(false)
    57         , m_reversed(false)
     59        , m_dirOverride(false)
    5860        , m_treatAsText(true)
    5961        , m_determinedIfNextOnLineExists(false)
     
    8183        , m_firstLine(firstLine)
    8284        , m_constructed(constructed)
     85        , m_bidiEmbeddingLevel(0)
    8386        , m_dirty(dirty)
    8487        , m_extracted(extracted)
     
    8992        , m_hasSelectedChildren(false)   
    9093        , m_hasEllipsisBox(false)
    91         , m_reversed(false)
     94        , m_dirOverride(false)
    9295        , m_treatAsText(true)
    9396        , m_determinedIfNextOnLineExists(false)
     
    212215    virtual int caretMaxOffset() const;
    213216    virtual unsigned caretMaxRenderedOffset() const;
    214    
     217
     218    unsigned char bidiLevel() const { return m_bidiEmbeddingLevel; }
     219    void setBidiLevel(unsigned char level) { m_bidiEmbeddingLevel = level; }
     220    TextDirection direction() const { return m_bidiEmbeddingLevel % 2 ? RTL : LTR; }
     221    int caretLeftmostOffset() const { return direction() == LTR ? caretMinOffset() : caretMaxOffset(); }
     222    int caretRightmostOffset() const { return direction() == LTR ? caretMaxOffset() : caretMinOffset(); }
     223
    215224    virtual void clearTruncation() { }
    216225
     
    251260private:
    252261    bool m_constructed : 1;
     262    unsigned char m_bidiEmbeddingLevel : 6;
    253263protected:
    254264    bool m_dirty : 1;
     
    267277    // for InlineTextBox
    268278public:
    269     bool m_reversed : 1;
    270279    bool m_dirOverride : 1;
    271280    bool m_treatAsText : 1; // Whether or not to treat a <br> as text for the purposes of line height.
  • trunk/WebCore/rendering/InlineTextBox.cpp

    r31200 r32508  
    9898    const Font& f = textObj->style(m_firstLine)->font();
    9999
    100     IntRect r = enclosingIntRect(f.selectionRectForText(TextRun(textObj->text()->characters() + m_start, m_len, textObj->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride),
     100    IntRect r = enclosingIntRect(f.selectionRectForText(TextRun(textObj->text()->characters() + m_start, m_len, textObj->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride),
    101101                                                        IntPoint(tx + m_x, ty + selTop), selHeight, sPos, ePos));
    102102    if (r.x() > tx + m_x + m_width)
     
    148148
    149149        if (ellipsisX < m_x + m_width) {
    150             if (m_reversed)
     150            if (direction() == RTL)
    151151                return -1; // FIXME: Support LTR truncation when the last run is RTL someday.
    152152
     
    386386        if (m_truncation != cNoTruncation)
    387387            endPoint = m_truncation;
    388         paintInfo.context->drawText(TextRun(textStr->characters() + m_start, endPoint, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || styleToUse->visuallyOrdered()),
     388        paintInfo.context->drawText(TextRun(textStr->characters() + m_start, endPoint, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || styleToUse->visuallyOrdered()),
    389389                                    IntPoint(m_x + tx, m_y + ty + m_baseline));
    390390    } else {
     
    394394            // paint only the text that is not selected
    395395            if (sPos >= ePos)
    396                 paintInfo.context->drawText(TextRun(textStr->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || styleToUse->visuallyOrdered()),
     396                paintInfo.context->drawText(TextRun(textStr->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || styleToUse->visuallyOrdered()),
    397397                                            IntPoint(m_x + tx, m_y + ty + m_baseline));
    398398            else {
    399399                if (sPos - 1 >= 0)
    400                     paintInfo.context->drawText(TextRun(textStr->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || styleToUse->visuallyOrdered()),
     400                    paintInfo.context->drawText(TextRun(textStr->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || styleToUse->visuallyOrdered()),
    401401                                                IntPoint(m_x + tx, m_y + ty + m_baseline),  0, sPos);
    402402                if (ePos < m_start + m_len)
    403                     paintInfo.context->drawText(TextRun(textStr->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || styleToUse->visuallyOrdered()),
     403                    paintInfo.context->drawText(TextRun(textStr->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || styleToUse->visuallyOrdered()),
    404404                                                IntPoint(m_x + tx, m_y + ty + m_baseline), ePos);
    405405            }
     
    416416                paintInfo.context->setShadow(IntSize(selectionTextShadow->x, selectionTextShadow->y),
    417417                                             selectionTextShadow->blur, selectionTextShadow->color);
    418             paintInfo.context->drawText(TextRun(textStr->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || styleToUse->visuallyOrdered()),
     418            paintInfo.context->drawText(TextRun(textStr->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || styleToUse->visuallyOrdered()),
    419419                                        IntPoint(m_x + tx, m_y + ty + m_baseline), sPos, ePos);
    420420            if (selectionTextShadow)
     
    509509    int h = selectionHeight();
    510510    p->clip(IntRect(m_x + tx, y + ty, m_width, h));
    511     p->drawHighlightForText(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered()),
     511    p->drawHighlightForText(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
    512512                            IntPoint(m_x + tx, y + ty), h, c, sPos, ePos);
    513513    p->restore();
     
    531531    int y = selectionTop();
    532532    int h = selectionHeight();
    533     p->drawHighlightForText(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered()),
     533    p->drawHighlightForText(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
    534534                            IntPoint(m_x + tx, y + ty), h, c, sPos, ePos);
    535535    p->restore();
     
    630630        int startPosition = max(marker.startOffset - m_start, (unsigned)0);
    631631        int endPosition = min(marker.endOffset - m_start, (unsigned)m_len);   
    632         TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered());
     632        TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
    633633        IntRect markerRect = enclosingIntRect(f->selectionRectForText(run, startPoint, selectionHeight(), startPosition, endPosition));
    634634        object()->document()->setRenderedRectForMarker(object()->node(), marker, markerRect);
     
    663663    int sPos = max(marker.startOffset - m_start, (unsigned)0);
    664664    int ePos = min(marker.endOffset - m_start, (unsigned)m_len);   
    665     TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered());
     665    TextRun run(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered());
    666666    IntPoint startPoint = IntPoint(m_x + tx, y + ty);
    667667   
     
    802802       
    803803    RenderBlock *blockElement = object()->containingBlock();
    804     return m_reversed ? xPos() - blockElement->borderRight() - blockElement->paddingRight()
     804    return direction() == RTL ? xPos() - blockElement->borderRight() - blockElement->paddingRight()
    805805                      : xPos() - blockElement->borderLeft() - blockElement->paddingLeft();
    806806}
     
    814814    RenderStyle *style = text->style(m_firstLine);
    815815    const Font* f = &style->font();
    816     return f->offsetForPosition(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride || style->visuallyOrdered()),
     816    return f->offsetForPosition(TextRun(textObject()->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride || style->visuallyOrdered()),
    817817                                _x - m_x, includePartialGlyphs);
    818818}
     
    825825    RenderText* text = static_cast<RenderText*>(m_object);
    826826    const Font& f = text->style(m_firstLine)->font();
    827     int from = m_reversed ? offset - m_start : 0;
    828     int to = m_reversed ? m_len : offset - m_start;
     827    int from = direction() == RTL ? offset - m_start : 0;
     828    int to = direction() == RTL ? m_len : offset - m_start;
    829829    // FIXME: Do we need to add rightBearing here?
    830     return enclosingIntRect(f.selectionRectForText(TextRun(text->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, m_reversed, m_dirOverride),
     830    return enclosingIntRect(f.selectionRectForText(TextRun(text->text()->characters() + m_start, m_len, textObject()->allowTabs(), textPos(), m_toAdd, direction() == RTL, m_dirOverride),
    831831                                                   IntPoint(m_x, 0), 0, from, to)).right();
    832832}
  • trunk/WebCore/rendering/RenderBR.cpp

    r29098 r32508  
    109109}
    110110
    111 InlineBox* RenderBR::inlineBox(int /*offset*/, EAffinity /*affinity*/)
    112 {
    113     return firstTextBox();
    114 }
    115 
    116111} // namespace WebCore
  • trunk/WebCore/rendering/RenderBR.h

    r25754 r32508  
    6161    virtual VisiblePosition positionForCoordinates(int x, int y);
    6262
    63     virtual InlineBox* inlineBox(int offset, EAffinity = UPSTREAM);
    64 
    6563private:
    6664    mutable short m_lineHeight;
  • trunk/WebCore/rendering/RenderBox.cpp

    r32446 r32508  
    25232523}
    25242524
    2525 IntRect RenderBox::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine)
     2525IntRect RenderBox::caretRect(InlineBox* box, int caretOffset, int* extraWidthToEndOfLine)
    25262526{
    25272527    // VisiblePositions at offsets inside containers either a) refer to the positions before/after
     
    25332533    const int caretWidth = 1;
    25342534    IntRect rect(xPos(), yPos(), caretWidth, m_height);
    2535     if (offset)
     2535    TextDirection direction = box ? box->direction() : style()->direction();
     2536
     2537    if ((!caretOffset) ^ (direction == LTR))
    25362538        rect.move(IntSize(m_width - caretWidth, 0));
    2537     if (InlineBox* box = inlineBoxWrapper()) {
     2539
     2540    if (box) {
    25382541        RootInlineBox* rootBox = box->root();
    25392542        int top = rootBox->topOverflow();
  • trunk/WebCore/rendering/RenderBox.h

    r32406 r32508  
    140140    virtual RenderLayer* layer() const { return m_layer; }
    141141
    142     virtual IntRect caretRect(int offset, EAffinity = UPSTREAM, int* extraWidthToEndOfLine = 0);
     142    virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
    143143
    144144    virtual void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, int clipY, int clipHeight,
  • trunk/WebCore/rendering/RenderFlow.cpp

    r32446 r32508  
    621621}
    622622
    623 IntRect RenderFlow::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine)
     623IntRect RenderFlow::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
    624624{
    625625    // Do the normal calculation in most cases.
    626626    if (firstChild() || style()->display() == INLINE)
    627         return RenderContainer::caretRect(offset, affinity, extraWidthToEndOfLine);
     627        return RenderContainer::caretRect(inlineBox, caretOffset, extraWidthToEndOfLine);
    628628
    629629    // This is a special case:
  • trunk/WebCore/rendering/RenderFlow.h

    r31127 r32508  
    9494    virtual int leftmostPosition(bool includeOverflowInterior = true, bool includeSelf = true) const;
    9595
    96     virtual IntRect caretRect(int offset, EAffinity = UPSTREAM, int* extraWidthToEndOfLine = 0);
     96    virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
    9797
    9898    virtual void addFocusRingRects(GraphicsContext*, int tx, int ty);
  • trunk/WebCore/rendering/RenderObject.cpp

    r32446 r32508  
    23452345}
    23462346
    2347 IntRect RenderObject::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine)
     2347IntRect RenderObject::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
    23482348{
    23492349   if (extraWidthToEndOfLine)
     
    29562956int RenderObject::caretMaxOffset() const
    29572957{
    2958     return isReplaced() ? 1 : 0;
     2958    return isReplaced() ? (element() ? max(1U, element()->childNodeCount()) : 1) : 0;
    29592959}
    29602960
     
    29722972{
    29732973    return current + 1;
    2974 }
    2975 
    2976 InlineBox* RenderObject::inlineBox(int offset, EAffinity affinity)
    2977 {
    2978     return inlineBoxWrapper();
    29792974}
    29802975
  • trunk/WebCore/rendering/RenderObject.h

    r32446 r32508  
    434434    virtual void deleteLineBoxWrapper();
    435435
    436     virtual InlineBox* inlineBox(int offset = 0, EAffinity = UPSTREAM);
    437 
    438436    // for discussion of lineHeight see CSS2 spec
    439437    virtual short lineHeight(bool firstLine, bool isRootLineBox = false) const;
     
    833831     * useful for character range rect computations
    834832     */
    835     virtual IntRect caretRect(int offset, EAffinity = UPSTREAM, int* extraWidthToEndOfLine = 0);
     833    virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
    836834
    837835    virtual int lowestPosition(bool /*includeOverflowInterior*/ = true, bool /*includeSelf*/ = true) const { return 0; }
  • trunk/WebCore/rendering/RenderReplaced.cpp

    r32446 r32508  
    197197}
    198198
    199 int RenderReplaced::caretMinOffset() const
    200 {
    201     return 0;
    202 }
    203 
    204 // Returns 1 since a replaced element can have the caret positioned
    205 // at its beginning (0), or at its end (1).
    206 // NOTE: Yet, "select" elements can have any number of "option" elements
    207 // as children, so this "0 or 1" idea does not really hold up.
    208 int RenderReplaced::caretMaxOffset() const
    209 {
    210     return 1;
    211 }
    212 
    213199unsigned RenderReplaced::caretMaxRenderedOffset() const
    214200{
  • trunk/WebCore/rendering/RenderReplaced.h

    r31155 r32508  
    5656    virtual IntRect overflowRect(bool includeInterior = true) const;
    5757
    58     virtual int caretMinOffset() const;
    59     virtual int caretMaxOffset() const;
    6058    virtual unsigned caretMaxRenderedOffset() const;
    6159    virtual VisiblePosition positionForCoordinates(int x, int y);
  • trunk/WebCore/rendering/RenderSVGInlineText.cpp

    r29663 r32508  
    123123}
    124124
    125 IntRect RenderSVGInlineText::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine)
     125IntRect RenderSVGInlineText::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
    126126{
    127127    // SVG doesn't have any editable content where a caret rect would be needed
     
    147147        if (box->svgCharacterHitsPosition(x + object->xPos(), y + object->yPos(), offset)) {
    148148            // If we're not at the end/start of the box, stop looking for other selected boxes.
    149             if (!box->m_reversed) {
     149            if (box->direction() == LTR) {
    150150                if (offset <= (int) box->end() + 1)
    151151                    break;
  • trunk/WebCore/rendering/RenderSVGInlineText.h

    r29663 r32508  
    4040    virtual InlineTextBox* createInlineTextBox();
    4141
    42     virtual IntRect caretRect(int offset, EAffinity, int* extraWidthToEndOfLine = 0);
     42    virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
    4343    virtual VisiblePosition positionForCoordinates(int x, int y);
    4444
  • trunk/WebCore/rendering/RenderText.cpp

    r31945 r32508  
    325325}
    326326
    327 static inline bool atLineWrap(InlineTextBox* box, int offset)
    328 {
    329     return box->nextTextBox() && !box->nextOnLine() && offset == box->m_start + box->m_len;
    330 }
    331 
    332 IntRect RenderText::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine)
    333 {
    334     if (!firstTextBox() || !textLength())
     327IntRect RenderText::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
     328{
     329    if (!inlineBox)
    335330        return IntRect();
    336331
    337     // Find the text box for the given offset
    338     InlineTextBox* box = 0;
    339     for (box = firstTextBox(); box; box = box->nextTextBox()) {
    340         if (box->containsCaretOffset(offset)) {
    341             // Check if downstream affinity would make us move to the next line.
    342             if (atLineWrap(box, offset) && affinity == DOWNSTREAM) {
    343                 // Use the next text box
    344                 box = box->nextTextBox();
    345                 offset = box->m_start;
    346             } else {
    347                 InlineTextBox* prevBox = box->prevTextBox();
    348                 if (offset == box->m_start && affinity == UPSTREAM && prevBox && !box->prevOnLine()) {
    349                     box = prevBox;
    350                     offset = box->m_start + box->m_len;
    351                 }
    352             }
    353             break;
    354         }
    355     }
    356 
    357     if (!box)
     332    ASSERT(inlineBox->isInlineTextBox());
     333    if (!inlineBox->isInlineTextBox())
    358334        return IntRect();
     335
     336    InlineTextBox* box = static_cast<InlineTextBox*>(inlineBox);
    359337
    360338    int height = box->root()->bottomOverflow() - box->root()->topOverflow();
    361339    int top = box->root()->topOverflow();
    362340
    363     int left = box->positionForOffset(offset);
     341    int left = box->positionForOffset(caretOffset);
    364342
    365343    int rootLeft = box->root()->xPos();
     
    377355    if (style()->autoWrap()) {
    378356        int availableWidth = cb->lineWidth(top);
    379         if (!box->m_reversed)
     357        if (box->direction() == LTR)
    380358            left = min(left, absx + rootLeft + availableWidth - 1);
    381359        else
     
    1006984    }
    1007985
    1008     m_containsReversedText |= s->m_reversed;
     986    m_containsReversedText |= s->direction() == RTL;
    1009987}
    1010988
     
    11721150}
    11731151
    1174 InlineBox* RenderText::inlineBox(int offset, EAffinity affinity)
    1175 {
    1176     for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
    1177         if (box->containsCaretOffset(offset)) {
    1178             if (atLineWrap(box, offset) && affinity == DOWNSTREAM)
    1179                 return box->nextTextBox();
    1180             return box;
    1181         }
    1182         if (offset < box->m_start)
    1183             // The offset we're looking for is before this node
    1184             // this means the offset must be in content that is
    1185             // not rendered.
    1186             return box->prevTextBox() ? box->prevTextBox() : firstTextBox();
    1187     }
    1188 
    1189     return 0;
    1190 }
    1191 
    11921152#ifndef NDEBUG
    11931153
  • trunk/WebCore/rendering/RenderText.h

    r30412 r32508  
    106106    virtual void setSelectionState(SelectionState s);
    107107    virtual IntRect selectionRect(bool clipToVisibleContent = true);
    108     virtual IntRect caretRect(int offset, EAffinity, int* extraWidthToEndOfLine = 0);
     108    virtual IntRect caretRect(InlineBox*, int caretOffset, int* extraWidthToEndOfLine = 0);
    109109
    110110    virtual int marginLeft() const { return style()->marginLeft().calcMinValue(0); }
     
    115115    InlineTextBox* firstTextBox() const { return m_firstTextBox; }
    116116    InlineTextBox* lastTextBox() const { return m_lastTextBox; }
    117 
    118     virtual InlineBox* inlineBox(int offset, EAffinity = UPSTREAM);
    119117
    120118    virtual int caretMinOffset() const;
  • trunk/WebCore/rendering/RenderTextControl.cpp

    r31086 r32508  
    632632        return "";
    633633
    634     InlineBox* box = renderer->inlineBox(0, DOWNSTREAM);
     634    InlineBox* box = renderer->isText() ? static_cast<RenderText*>(renderer)->firstTextBox() : renderer->inlineBoxWrapper();
    635635    if (!box)
    636636        return "";
  • trunk/WebCore/rendering/RenderTreeAsText.cpp

    r32231 r32508  
    306306{
    307307    ts << "text run at (" << run.m_x << "," << run.m_y << ") width " << run.m_width;
    308     if (run.m_reversed || run.m_dirOverride) {
    309         ts << (run.m_reversed ? " RTL" : " LTR");
     308    if (run.direction() == RTL || run.m_dirOverride) {
     309        ts << (run.direction() == RTL ? " RTL" : " LTR");
    310310        if (run.m_dirOverride)
    311311            ts << " override";
  • trunk/WebCore/rendering/SVGInlineTextBox.cpp

    r31342 r32508  
    100100    int charsConsumed;
    101101    String glyphName;
    102     if (!m_reversed)
     102    if (direction() == LTR)
    103103        glyphWidth = calculateGlyphWidth(style, offset, 0, charsConsumed, glyphName);
    104104    else
     
    149149            // Take RTL text into account and pick right glyph width/height.
    150150            // NOTE: This offset has to be corrected _after_ calling calculateGlyphBoundaries
    151             if (textBox->m_reversed)
     151            if (textBox->direction() == RTL)
    152152                newOffset = textBox->start() + textBox->end() - newOffset;
    153153
     
    249249    FloatRect glyphRect = calculateGlyphBoundaries(style, offset, charAtPos);
    250250
    251     if (m_reversed)
     251    if (direction() == RTL)
    252252        offset++;
    253253
     
    261261    // Check whether x position hits the current character
    262262    if (x < charAtPos.x) {
    263         if (offset > 0 && !m_reversed)
     263        if (offset > 0 && direction() == LTR)
    264264            return true;
    265         else if (offset < (int) end() && m_reversed)
     265        else if (offset < (int) end() && direction() == RTL)
    266266            return true;
    267267
     
    275275    // Snap to character at half of it's advance
    276276    if (x >= charAtPos.x + glyphRect.width() / 2.0)
    277         offset += m_reversed ? -1 : 1;
     277        offset += direction() == RTL ? -1 : 1;
    278278
    279279    return true;
  • trunk/WebCore/rendering/SVGRenderTreeAsText.cpp

    r30418 r32508  
    424424                ts << " width " << cummulatedWidthOfInlineBoxCharacterRange(range);
    425425
    426             if (textBox->m_reversed || textBox->m_dirOverride) {
    427                 ts << (textBox->m_reversed ? " RTL" : " LTR");
     426            if (textBox->direction() == RTL || textBox->m_dirOverride) {
     427                ts << (textBox->direction() == RTL ? " RTL" : " LTR");
    428428
    429429                if (textBox->m_dirOverride)
  • trunk/WebCore/rendering/SVGRootInlineBox.cpp

    r31600 r32508  
    649649    ASSERT(style);
    650650
    651     TextRun run(c, len, false, static_cast<int>(xPos), textBox->toAdd(), textBox->m_reversed, textBox->m_dirOverride || style->visuallyOrdered());
     651    TextRun run(c, len, false, static_cast<int>(xPos), textBox->toAdd(), textBox->direction() == RTL, textBox->m_dirOverride || style->visuallyOrdered());
    652652
    653653#if ENABLE(SVG_FONTS)
     
    710710                SVGChar& currentCharacter = *itSearch;
    711711
    712                 int offset = box->m_reversed ? box->end() - i - positionOffset + 1 : box->start() + i + positionOffset - 1;
     712                int offset = box->direction() == RTL ? box->end() - i - positionOffset + 1 : box->start() + i + positionOffset - 1;
    713713
    714714                // FIXME: does this need to change to handle multichar glyphs?
     
    11311131        String unicodeStr;
    11321132        String glyphName;
    1133         if (textBox->m_reversed) {
     1133        if (textBox->direction() == RTL) {
    11341134            glyphWidth = svgTextBox->calculateGlyphWidth(style, textBox->end() - i, extraCharsAvailable, charsConsumed, glyphName);
    11351135            glyphHeight = svgTextBox->calculateGlyphHeight(style, textBox->end() - i, extraCharsAvailable);
     
    11901190        float spacing = font.letterSpacing() + calculateKerning(textBox->object()->element()->renderer());
    11911191
    1192         const UChar* currentCharacter = text->characters() + (textBox->m_reversed ? textBox->end() - i : textBox->start() + i);
     1192        const UChar* currentCharacter = text->characters() + (textBox->direction() == RTL ? textBox->end() - i : textBox->start() + i);
    11931193        const UChar* lastCharacter = 0;
    11941194
    1195         if (textBox->m_reversed) {
     1195        if (textBox->direction() == RTL) {
    11961196            if (i < textBox->end())
    11971197                lastCharacter = text->characters() + textBox->end() - i +  1;
  • trunk/WebCore/rendering/bidi.cpp

    r32402 r32508  
    519519        if (runCount == 2 && !r->m_object->isListMarker())
    520520            isOnlyRun = ((style()->direction() == RTL) ? lastRun : firstRun)->m_object->isListMarker();
    521         r->m_box = r->m_object->createInlineBox(r->m_object->isPositioned(), false, isOnlyRun);
    522 
    523         if (r->m_box) {
     521
     522        InlineBox* box = r->m_object->createInlineBox(r->m_object->isPositioned(), false, isOnlyRun);
     523        r->m_box = box;
     524
     525        if (box) {
    524526            // If we have no parent box yet, or if the run is not simply a sibling,
    525527            // then we need to construct inline boxes as necessary to properly enclose the
     
    530532
    531533            // Append the inline box to this line.
    532             parentBox->addToLine(r->m_box);
    533            
    534             if (r->m_box->isInlineTextBox()) {
    535                 InlineTextBox* text = static_cast<InlineTextBox*>(r->m_box);
     534            parentBox->addToLine(box);
     535
     536            bool visuallyOrdered = r->m_object->style()->visuallyOrdered();
     537            box->setBidiLevel(visuallyOrdered ? 0 : r->level());
     538
     539            if (box->isInlineTextBox()) {
     540                InlineTextBox* text = static_cast<InlineTextBox*>(box);
    536541                text->setStart(r->m_start);
    537542                text->setLen(r->m_stop - r->m_start);
    538                 bool visuallyOrdered = r->m_object->style()->visuallyOrdered();
    539                 text->m_reversed = r->reversed(visuallyOrdered);
    540543                text->m_dirOverride = r->dirOverride(visuallyOrdered);
    541544            }
  • trunk/WebCore/svg/SVGTextContentElement.cpp

    r31857 r32508  
    7575
    7676            // Take RTL text into account and pick right glyph width/height.
    77             if (textBox->m_reversed)
     77            if (textBox->direction() == RTL)
    7878                newOffset = textBox->start() + textBox->end() - newOffset;
    7979
     
    192192
    193193                    // Take RTL text into account and pick right glyph width/height.
    194                     if (textBox->m_reversed)
     194                    if (textBox->direction() == RTL)
    195195                        newOffset = textBox->start() + textBox->end() - newOffset;
    196196
  • trunk/WebKit/mac/ChangeLog

    r32505 r32508  
     12008-04-24  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Darin Adler.
     4
     5        - preparation for https://bugs.webkit.org/show_bug.cgi?id=3729
     6          <rdar://problem/4036353> REGRESSION: arrow keys move insertion bar backwards in RTL text
     7
     8        * WebView/WebFrame.mm:
     9        (-[WebFrame _caretRectAtNode:offset:affinity:]): Changed to use
     10        VisiblePosition::caretRect() instead of the RenderObject method which
     11        was removed.
     12
    1132008-04-24  Brady Eidson  <beidson@apple.com>
    214
  • trunk/WebKit/mac/WebView/WebFrame.mm

    r32042 r32508  
    617617- (NSRect)_caretRectAtNode:(DOMNode *)node offset:(int)offset affinity:(NSSelectionAffinity)affinity
    618618{
    619     return [node _node]->renderer()->caretRect(offset, static_cast<EAffinity>(affinity));
     619    VisiblePosition visiblePosition([node _node], offset, static_cast<EAffinity>(affinity));
     620    return visiblePosition.caretRect();
    620621}
    621622
Note: See TracChangeset for help on using the changeset viewer.