Changeset 43032 in webkit


Ignore:
Timestamp:
Apr 29, 2009, 5:48:43 PM (16 years ago)
Author:
mitz@apple.com
Message:

WebCore:

2009-04-29 Xiaomei Ji <xji@chromium.org>

Reviewed by Dan Bernstein.

Fix https://bugs.webkit.org/show_bug.cgi?id=24168
RTL: Home/End key does not behave correctly in mixed bidi text in RTL document

Test: editing/selection/home-end.html

  • editing/SelectionController.cpp: (WebCore::SelectionController::modifyExtendingForward): Change calling endOfLine() to logicalEndOfLine() when granularity is LineBoundary. (WebCore::SelectionController::modifyMovingForward): Change calling endOfLine() to logicalEndOfLine() when granularity is LineBoundary (WebCore::SelectionController::modifyExtendingBackward): Change calling startOfLine() to logicalStartOfLine() when granularity is LineBoundary. (WebCore::SelectionController::modifyMovingBackward): Change calling startOfLine() to logicalStartOfLine() when granularity is LineBoundary.
  • editing/visible_units.cpp: (WebCore::getLeafBoxesInLogicalOrder): Added. Reconstruct leaf boxes in logical order. (WebCore::getLogicalStartBoxAndNode): Added. (WebCore::getLogicalEndBoxAndNode): Added. (WebCore::logicalStartPositionForLine): Added. Similar to startPositionForLine. (WebCore::logicalStartOfLine): Added. Similar to startOfLine. (WebCore::logicalEndPositionForLine): Added. Similar to endPositionForLine. (WebCore::inSameLogicalLine): Added. (WebCore::logicalEndOfLine): Added. Similar to endOfLine.
  • editing/visible_units.h:

LayoutTests:

2009-04-29 Xiaomei Ji <xji@chromium.org>

Reviewed by Dan Bernstein.

Fix https://bugs.webkit.org/show_bug.cgi?id=24168
RTL: Home/End key does not behave correctly in mixed bidi text in RTL document

  • editing/selection/extend-selection-expected.txt: Added result for extend in lineBoundary.
  • editing/selection/extend-selection.html: Added test cases and script for extend in lineBoundary.
  • editing/selection/home-end-expected.txt: Added.
  • editing/selection/home-end.html: Added.
Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r43031 r43032  
     12009-04-29  Xiaomei Ji  <xji@chromium.org>
     2
     3        Reviewed by Dan Bernstein.
     4
     5        Fix https://bugs.webkit.org/show_bug.cgi?id=24168
     6        RTL: Home/End key does not behave correctly in mixed bidi text in RTL document
     7
     8        * editing/selection/extend-selection-expected.txt: Added result for extend in
     9        lineBoundary.
     10        * editing/selection/extend-selection.html: Added test cases and script for extend
     11        in lineBoundary.
     12        * editing/selection/home-end-expected.txt: Added.
     13        * editing/selection/home-end.html: Added.
     14
    1152009-04-29  Ojan Vafai  <ojan@chromium.org>
    216
  • trunk/LayoutTests/editing/selection/extend-selection-expected.txt

    r43028 r43032  
    1010ipsum dolor sit
    1111amett
     12Lorem ipsum dolor sit amet
     13Lorem ipsum dolor
     14just a test
     15sit amet
     16Lorem ipsum dolor sit amet
     17Lorem
     18ipsum dolor sit
     19amet
     20Just testing רק בודק
     21Just testing what ever
     22car means אבג.
     23car דהו אבג.
     24he said " car דהו אבג ."
     25זחט יךכ לםמ ' he said " car דהו אבג " '?
     26אבג abc דהו
     27edf זחט abrebg
     28abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg
     29abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg
    1230
    1331
     
    373391  Extending left:  " amett"[(0,6), (0,1)], "ipsum dolor sit"[(0,12), (0,6), (0,0)], "Lorem "[(0,0), (0,5)]
    374392
     393
     394
     395Extending by lineBoundary
     396Test 1, LTR:
     397  Extending forward: "\nabc ABC xyz DEF def\n"[(1,1), (1,20)]
     398  Extending backward:  "\nabc ABC xyz DEF def\n"[(1,20), (1,1)]
     399Test 1, RTL:
     400  Extending forward: "\nabc ABC xyz DEF def\n"[(1,1), (1,20)]
     401  Extending backward:  "\nabc ABC xyz DEF def\n"[(1,20), (1,1)]
     402Test 2, LTR:
     403  Extending forward: "\nABC xyz DEF def GHI\n"[(1,1), (1,20)]
     404  Extending backward:  "\nABC xyz DEF def GHI\n"[(1,20), (1,1)]
     405Test 2, RTL:
     406  Extending forward: "\nABC xyz DEF def GHI\n"[(1,1), (1,20)]
     407  Extending backward:  "\nABC xyz DEF def GHI\n"[(1,20), (1,1)]
     408Test 3, LTR:
     409  Extending forward: "\nABC DEF ABC\n"[(1,1), (1,12)]
     410  Extending backward:  "\nABC DEF ABC\n"[(1,12), (1,1)]
     411Test 3, RTL:
     412  Extending forward: "\nABC DEF ABC\n"[(1,1), (1,12)]
     413  Extending backward:  "\nABC DEF ABC\n"[(1,12), (1,1)]
     414Test 4, LTR:
     415  Extending forward: "\nabc efd dabeb\n"[(1,1), (1,14)]
     416  Extending backward:  "\nabc efd dabeb\n"[(1,14), (1,1)]
     417Test 4, RTL:
     418  Extending forward: "\nabc efd dabeb\n"[(1,1), (1,14)]
     419  Extending backward:  "\nabc efd dabeb\n"[(1,14), (1,1)]
     420Test 5, LTR:
     421  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     422  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     423Test 5, RTL:
     424  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     425  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     426Test 6, LTR:
     427  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     428  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     429Test 6, RTL:
     430  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     431  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     432Test 7, LTR:
     433  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     434  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     435Test 7, RTL:
     436  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     437  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     438Test 8, LTR:
     439  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     440  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     441Test 8, RTL:
     442  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     443  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     444Test 9, LTR:
     445  Extending forward: "Lorem "[(0,0), (0,5)]
     446  Extending backward:  "Lorem "[(0,5), (0,0)]
     447Test 9, RTL:
     448  Extending forward: "Lorem "[(0,0), (0,5)]
     449  Extending backward:  "Lorem "[(0,5), (0,0)]
     450Test 10, LTR:
     451  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     452  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     453Test 10, RTL:
     454  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     455  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     456Test 11, LTR:
     457  Extending forward: "Lorem "[(0,0)], "ipsum dolor"[(0,11)]
     458  Extending backward:  "ipsum dolor"[(0,11)], "Lorem "[(0,0)]
     459Test 11, RTL:
     460  Extending forward: "Lorem "[(0,0)], "ipsum dolor"[(0,11)]
     461  Extending backward:  "ipsum dolor"[(0,11)], "Lorem "[(0,0)]
     462Test 12, LTR:
     463  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     464  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     465Test 12, RTL:
     466  Extending forward: "Lorem "[(0,0)], " amet"[(0,5)]
     467  Extending backward:  " amet"[(0,5)], "Lorem "[(0,0)]
     468Test 13, LTR:
     469  Extending forward: "Lorem "[(0,0), (0,5)]
     470  Extending backward:  "Lorem "[(0,5), (0,0)]
     471Test 13, RTL:
     472  Extending forward: "Lorem "[(0,0), (0,5)]
     473  Extending backward:  "Lorem "[(0,5), (0,0)]
     474Test 14, LTR:
     475  Extending forward: "\n Just\n "[(2,2)], "\n BFDX\n"[(2,6)]
     476  Extending backward:  "\n BFDX\n"[(2,6)], "\n Just\n "[(2,2)]
     477Test 14, RTL:
     478  Extending forward: "\n Just\n "[(2,2)], "\n BFDX\n"[(2,6)]
     479  Extending backward:  "\n BFDX\n"[(2,6)], "\n Just\n "[(2,2)]
     480Test 15, LTR:
     481  Extending forward: "\n Just\n "[(2,2)], "\n ever\n"[(2,6)]
     482  Extending backward:  "\n ever\n"[(2,6)], "\n Just\n "[(2,2)]
     483Test 15, RTL:
     484  Extending forward: "\n Just\n "[(2,2)], "\n ever\n"[(2,6)]
     485  Extending backward:  "\n ever\n"[(2,6)], "\n Just\n "[(2,2)]
     486Test 16, LTR:
     487  Extending forward: "car means ABC."[(0,0), (0,14)]
     488  Extending backward:  "car means ABC."[(0,14), (0,0)]
     489Test 16, RTL:
     490  Extending forward: "car means ABC."[(0,0), (0,14)]
     491  Extending backward:  "car means ABC."[(0,14), (0,0)]
     492Test 17, LTR:
     493  Extending forward: "᪜car DEF ABC.᪝"[(1,1), (1,13)]
     494  Extending backward:  "᪜car DEF ABC.᪝"[(1,13), (1,1)]
     495Test 17, RTL:
     496  Extending forward: "᪜car DEF ABC.᪝"[(1,1), (1,13)]
     497  Extending backward:  "᪜car DEF ABC.᪝"[(1,13), (1,1)]
     498Test 18, LTR:
     499  Extending forward: "he said "᪜car DEF ABC᪝.""[(0,0), (0,24)]
     500  Extending backward:  "he said "᪜car DEF ABC᪝.""[(0,24), (0,0)]
     501Test 18, RTL:
     502  Extending forward: "he said "᪜car DEF ABC᪝.""[(0,0), (0,24)]
     503  Extending backward:  "he said "᪜car DEF ABC᪝.""[(0,24), (0,0)]
     504Test 19, LTR:
     505  Extending forward: "GHI JKL MNO '᪛he said "᪜car DEF ABC᪝"᪝'?"[(0,0), (0,40)]
     506  Extending backward:  "GHI JKL MNO '᪛he said "᪜car DEF ABC᪝"᪝'?"[(0,40), (0,0)]
     507Test 19, RTL:
     508  Extending forward: "GHI JKL MNO '᪛he said "᪜car DEF ABC᪝"᪝'?"[(0,0), (0,40)]
     509  Extending backward:  "GHI JKL MNO '᪛he said "᪜car DEF ABC᪝"᪝'?"[(0,40), (0,0)]
     510Test 20, LTR:
     511  Extending forward: "ABC abc DEF"[(0,0), (0,11)]
     512  Extending backward:  "ABC abc DEF"[(0,11), (0,0)]
     513Test 20, RTL:
     514  Extending forward: "ABC abc DEF"[(0,0), (0,11)]
     515  Extending backward:  "ABC abc DEF"[(0,11), (0,0)]
     516Test 21, LTR:
     517  Extending forward: "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,0), (0,8), (0,16), (0,26), (0,34), (0,42), (0,50), (0,58), (0,66), (0,74), (0,82), (0,90), (0,98), (0,105)]
     518  Extending backward:  "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,105), (0,0)]
     519Test 21, RTL:
     520  Extending forward: "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,0), (0,7)]
     521  Extending backward:  "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,7), (0,0)]
     522Test 22, LTR:
     523  Extending forward: "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,0), (0,8), (0,16), (0,26), (0,34), (0,42), (0,50), (0,58), (0,66), (0,74), (0,82), (0,90), (0,98), (0,105)]
     524  Extending backward:  "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,105), (0,0)]
     525Test 22, RTL:
     526  Extending forward: "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,0), (0,7)]
     527  Extending backward:  "abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg "[(0,7), (0,0)]
     528
  • trunk/LayoutTests/editing/selection/extend-selection.html

    r43028 r43032  
    248248        }
    249249
     250        function testExtendingLineBoundary(tests, sel)
     251        {
     252            for (var i = 0; i < tests.length; ++i) {
     253                tests[i].style.direction = "ltr";
     254                log("Test " + (i + 1) + ", LTR:\n  Extending forward: ");
     255                sel.setPosition(tests[i], 0);
     256                var ltrRightPos = extendingSelection(sel, "forward", "lineBoundary", 0);
     257   
     258                log("  Extending backward:  ");
     259                var ltrLeftPos = extendingSelection(sel, "backward", "lineBoundary", 0);
     260
     261                tests[i].style.direction = "rtl";
     262                log("Test " + (i + 1) + ", RTL:\n  Extending forward: ");
     263                sel.setPosition(tests[i], 0);
     264                var ltrRightPos = extendingSelection(sel, "forward", "lineBoundary", 0);
     265   
     266                log("  Extending backward:  ");
     267                var ltrLeftPos = extendingSelection(sel, "backward", "lineBoundary", 0);
     268            }
     269        }
     270
    250271        onload = function()
    251272        {
     
    270291            log("\n\n\n\n\nExtending by word\n");
    271292            testExtendingSelectionForEnclosingBlock(tests,  sel, "word", 1);
     293
     294            tests = document.getElementsByClassName("home-end-test");
     295            var sel = getSelection();
     296            log("\n\n\nExtending by lineBoundary\n");
     297            testExtendingLineBoundary(tests,  sel);
    272298        }
    273299
     
    275301</head>
    276302<body>
    277 <div contenteditable class="test">
     303<div contenteditable class="test home-end-test">
    278304abc &#1488;&#1489;&#1490; xyz &#1491;&#1492;&#1493; def
    279305</div>
    280 <div contenteditable class="test">
     306<div contenteditable class="test home-end-test">
    281307&#1488;&#1489;&#1490; xyz &#1491;&#1492;&#1493; def &#1494;&#1495;&#1496;
    282308</div>
    283 <div contenteditable class="test">
     309<div contenteditable class="test home-end-test">
    284310&#1488;&#1489;&#1490; &#1491;&#1492;&#1493; &#1488;&#1489;&#1490;
    285311</div>
    286 <div contenteditable class="test">
     312<div contenteditable class="test home-end-test">
    287313abc efd dabeb
    288314</div>
    289315
    290316
    291 <div contenteditable  class="test">Lorem <span  style="direction: rtl">ipsum dolor sit</span> amet</div>
    292 <div contenteditable class="test">Lorem <span  dir="rtl">ipsum dolor sit</span> amet</div>
    293 <div contenteditable  class="test">Lorem <span  style="direction: ltr">ipsum dolor sit</span> amet</div>
    294 <div contenteditable class="test">Lorem <span  dir="ltr">ipsum dolor sit</span> amet</div>
    295 
    296 <div contenteditable class="testEnclosingBlock">Lorem <div  dir="rtl">ipsum dolor sit</div> amett</div>
     317<div contenteditable  class="test home-end-test">Lorem <span  style="direction: rtl">ipsum dolor sit</span> amet</div>
     318<div contenteditable class="test home-end-test">Lorem <span  dir="rtl">ipsum dolor sit</span> amet</div>
     319<div contenteditable  class="test home-end-test">Lorem <span  style="direction: ltr">ipsum dolor sit</span> amet</div>
     320<div contenteditable class="test home-end-test">Lorem <span  dir="ltr">ipsum dolor sit</span> amet</div>
     321
     322<div contenteditable class="testEnclosingBlock home-end-test">Lorem <div  dir="rtl">ipsum dolor sit</div> amett</div>
     323
     324<div contenteditable  class="home-end-test">Lorem <span  style="direction: ltr">ipsum dolor sit</span> amet</div>
     325<div contenteditable  class="home-end-test">Lorem <span  style="direction: ltr">ipsum dolor<div > just a test</div> sit</span> amet</div>
     326<div contenteditable class="home-end-test">Lorem <span  dir="ltr">ipsum dolor sit</span> amet</div>
     327<div contenteditable class="home-end-test">Lorem <div  dir="ltr">ipsum dolor sit</div> amet</div>
     328
     329<div class="home-end-test" contenteditable>
     330 Just
     331 <span>testing רק</span>
     332 בודק
     333</div>
     334
     335<div class="home-end-test" contenteditable>
     336 Just
     337 <span>testing what</span>
     338 ever
     339</div>
     340
     341
     342<div class="home-end-test" contenteditable>car means &#1488;&#1489;&#1490;.</div>
     343<div class="home-end-test" contenteditable>&#x202B;car &#1491;&#1492;&#1493; &#1488;&#1489;&#1490;.&#x202c;</div>
     344<div class="home-end-test" contenteditable>he said "&#x202B;car &#1491;&#1492;&#1493; &#1488;&#1489;&#1490;&#x202c;."</div>
     345<div class="home-end-test" contenteditable>&#1494;&#1495;&#1496; &#1497;&#1498;&#1499; &#1500;&#1501;&#1502; '&#x202a;he said "&#x202B;car &#1491;&#1492;&#1493; &#1488;&#1489;&#1490;&#x202c;"&#x202c;'?</div>
     346
     347
     348<div class="home-end-test" contenteditable>&#1488;&#1489;&#1490; abc &#1491;&#1492;&#1493;<br />edf &#1494;&#1495;&#1496; abrebg</div>
     349<div class="home-end-test" contenteditable style="line-break:before-white-space; width:100px">abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg </div>
     350<div class="home-end-test" contenteditable style="line-break:after-white-space; width:100px">abcdefg abcdefg abcdefg a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg </div>
    297351
    298352<pre id="console"></pre>
  • trunk/WebCore/ChangeLog

    r43028 r43032  
     12009-04-29  Xiaomei Ji  <xji@chromium.org>
     2
     3        Reviewed by Dan Bernstein.
     4
     5        Fix https://bugs.webkit.org/show_bug.cgi?id=24168
     6        RTL: Home/End key does not behave correctly in mixed bidi text in RTL document
     7
     8        Test: editing/selection/home-end.html
     9
     10        * editing/SelectionController.cpp:
     11        (WebCore::SelectionController::modifyExtendingForward): Change calling endOfLine()
     12        to logicalEndOfLine() when granularity is LineBoundary.
     13        (WebCore::SelectionController::modifyMovingForward): Change calling endOfLine()
     14        to logicalEndOfLine() when granularity is LineBoundary
     15        (WebCore::SelectionController::modifyExtendingBackward): Change calling
     16        startOfLine() to logicalStartOfLine() when granularity is LineBoundary.
     17        (WebCore::SelectionController::modifyMovingBackward): Change calling startOfLine()
     18        to logicalStartOfLine() when granularity is LineBoundary.
     19        * editing/visible_units.cpp:
     20        (WebCore::getLeafBoxesInLogicalOrder): Added. Reconstruct leaf boxes in logical order.
     21        (WebCore::getLogicalStartBoxAndNode): Added.
     22        (WebCore::getLogicalEndBoxAndNode): Added.
     23        (WebCore::logicalStartPositionForLine): Added. Similar to startPositionForLine.
     24        (WebCore::logicalStartOfLine): Added. Similar to startOfLine.
     25        (WebCore::logicalEndPositionForLine): Added. Similar to endPositionForLine.
     26        (WebCore::inSameLogicalLine): Added.
     27        (WebCore::logicalEndOfLine): Added. Similar to endOfLine.
     28        * editing/visible_units.h:
     29
    1302009-04-29  Eric Seidel  <eric@webkit.org>
    231
  • trunk/WebCore/editing/SelectionController.cpp

    r43028 r43032  
    322322            break;
    323323        case LineBoundary:
    324             pos = endOfLine(VisiblePosition(m_sel.end(), m_sel.affinity()));
     324            pos = logicalEndOfLine(VisiblePosition(m_sel.end(), m_sel.affinity()));
    325325            break;
    326326        case ParagraphBoundary:
     
    396396            break;
    397397        case LineBoundary:
    398             pos = endOfLine(VisiblePosition(m_sel.end(), m_sel.affinity()));
     398            pos = logicalEndOfLine(VisiblePosition(m_sel.end(), m_sel.affinity()));
    399399            break;
    400400        case ParagraphBoundary:
     
    475475            break;
    476476        case LineBoundary:
    477             pos = startOfLine(VisiblePosition(m_sel.start(), m_sel.affinity()));
     477            pos = logicalStartOfLine(VisiblePosition(m_sel.start(), m_sel.affinity()));
    478478            break;
    479479        case ParagraphBoundary:
     
    542542            break;
    543543        case LineBoundary:
    544             pos = startOfLine(VisiblePosition(m_sel.start(), m_sel.affinity()));
     544            pos = logicalStartOfLine(VisiblePosition(m_sel.start(), m_sel.affinity()));
    545545            break;
    546546        case ParagraphBoundary:
  • trunk/WebCore/editing/visible_units.cpp

    r43028 r43032  
    10561056}
    10571057
    1058 }
     1058static void getLeafBoxesInLogicalOrder(RootInlineBox* rootBox, Vector<InlineBox*>& leafBoxesInLogicalOrder) {
     1059    unsigned char minLevel = 128;
     1060    unsigned char maxLevel = 0;
     1061    unsigned count = 0;
     1062    InlineBox* r = rootBox->firstLeafChild();
     1063    // First find highest and lowest levels,
     1064    // and initialize leafBoxesInLogicalOrder with the leaf boxes in visual order.
     1065    while (r) {
     1066        if (r->bidiLevel() > maxLevel)
     1067            maxLevel = r->bidiLevel();
     1068        if (r->bidiLevel() < minLevel)
     1069            minLevel = r->bidiLevel();
     1070        leafBoxesInLogicalOrder.append(r);
     1071        r = r->nextLeafChild();
     1072        ++count;
     1073    }
     1074
     1075    if (rootBox->renderer()->style()->visuallyOrdered())
     1076        return;
     1077    // Reverse of reordering of the line (L2 according to Bidi spec):
     1078    // L2. From the highest level found in the text to the lowest odd level on each line,
     1079    // reverse any contiguous sequence of characters that are at that level or higher.
     1080
     1081    // Reversing the reordering of the line is only done up to the lowest odd level.
     1082    if (!(minLevel % 2))
     1083        minLevel++;
     1084   
     1085    InlineBox** end = leafBoxesInLogicalOrder.end();
     1086    while (minLevel <= maxLevel) {
     1087        InlineBox** iter = leafBoxesInLogicalOrder.begin();
     1088        while (iter != end) {
     1089            while (iter != end) {
     1090                if ((*iter)->bidiLevel() >= minLevel)
     1091                    break;
     1092                ++iter;
     1093            }
     1094            InlineBox** first = iter;
     1095            while (iter != end) {
     1096                if ((*iter)->bidiLevel() < minLevel)
     1097                    break;
     1098                ++iter;
     1099            }
     1100            InlineBox** last = iter;
     1101            std::reverse(first, last);
     1102        }               
     1103        ++minLevel;
     1104    }
     1105}
     1106
     1107static void getLogicalStartBoxAndNode(RootInlineBox* rootBox, InlineBox*& startBox, Node*& startNode)
     1108{
     1109    Vector<InlineBox*> leafBoxesInLogicalOrder;
     1110    getLeafBoxesInLogicalOrder(rootBox, leafBoxesInLogicalOrder);
     1111    startBox = 0;
     1112    startNode = 0;
     1113    for (size_t i = 0; i < leafBoxesInLogicalOrder.size(); ++i) {
     1114        startBox = leafBoxesInLogicalOrder[i];
     1115        startNode = startBox->renderer()->node();
     1116        if (startNode)
     1117            return;
     1118    }
     1119}
     1120
     1121static void getLogicalEndBoxAndNode(RootInlineBox* rootBox, InlineBox*& endBox, Node*& endNode)
     1122{
     1123    Vector<InlineBox*> leafBoxesInLogicalOrder;
     1124    getLeafBoxesInLogicalOrder(rootBox, leafBoxesInLogicalOrder);
     1125    endBox = 0;
     1126    endNode = 0;
     1127    // Generated content (e.g. list markers and CSS :before and :after
     1128    // pseudoelements) have no corresponding DOM element, and so cannot be
     1129    // represented by a VisiblePosition.  Use whatever precedes instead.
     1130    for (size_t i = leafBoxesInLogicalOrder.size(); i > 0; --i) {
     1131        endBox = leafBoxesInLogicalOrder[i - 1];
     1132        endNode = endBox->renderer()->node();
     1133        if (endNode)
     1134            return;
     1135    }
     1136}
     1137
     1138static VisiblePosition logicalStartPositionForLine(const VisiblePosition& c)
     1139{
     1140    if (c.isNull())
     1141        return VisiblePosition();
     1142
     1143    RootInlineBox* rootBox = rootBoxForLine(c);
     1144    if (!rootBox) {
     1145        // There are VisiblePositions at offset 0 in blocks without
     1146        // RootInlineBoxes, like empty editable blocks and bordered blocks.
     1147        Position p = c.deepEquivalent();
     1148        if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && !p.m_offset)
     1149            return positionAvoidingFirstPositionInTable(c);
     1150       
     1151        return VisiblePosition();
     1152    }
     1153   
     1154    InlineBox* logicalStartBox;
     1155    Node* logicalStartNode;
     1156    getLogicalStartBoxAndNode(rootBox, logicalStartBox, logicalStartNode);
     1157
     1158    if (!logicalStartNode)
     1159        return VisiblePosition();
     1160
     1161    int startOffset = logicalStartBox->caretMinOffset();
     1162 
     1163    VisiblePosition visPos = VisiblePosition(logicalStartNode, startOffset, DOWNSTREAM);
     1164    return positionAvoidingFirstPositionInTable(visPos);
     1165}
     1166
     1167VisiblePosition logicalStartOfLine(const VisiblePosition& c)
     1168{
     1169    VisiblePosition visPos = logicalStartPositionForLine(c);
     1170   
     1171    if (visPos.isNull())
     1172        return c.honorEditableBoundaryAtOrAfter(visPos);
     1173
     1174    return c.honorEditableBoundaryAtOrAfter(visPos);
     1175}
     1176
     1177static VisiblePosition logicalEndPositionForLine(const VisiblePosition& c)
     1178{
     1179    if (c.isNull())
     1180        return VisiblePosition();
     1181
     1182    RootInlineBox* rootBox = rootBoxForLine(c);
     1183    if (!rootBox) {
     1184        // There are VisiblePositions at offset 0 in blocks without
     1185        // RootInlineBoxes, like empty editable blocks and bordered blocks.
     1186        Position p = c.deepEquivalent();
     1187        if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && !p.m_offset)
     1188            return c;
     1189        return VisiblePosition();
     1190    }
     1191   
     1192    InlineBox* logicalEndBox;
     1193    Node* logicalEndNode;
     1194    getLogicalEndBoxAndNode(rootBox, logicalEndBox, logicalEndNode);
     1195    if (!logicalEndNode)
     1196        return VisiblePosition();
     1197   
     1198    int endOffset = 1;
     1199    if (logicalEndNode->hasTagName(brTag))
     1200        endOffset = 0;
     1201    else if (logicalEndBox->isInlineTextBox()) {
     1202        InlineTextBox* endTextBox = static_cast<InlineTextBox*>(logicalEndBox);
     1203        endOffset = endTextBox->start();
     1204        if (!endTextBox->isLineBreak())
     1205            endOffset += endTextBox->len();
     1206    }
     1207   
     1208    return VisiblePosition(logicalEndNode, endOffset, VP_UPSTREAM_IF_POSSIBLE);
     1209}
     1210
     1211bool inSameLogicalLine(const VisiblePosition& a, const VisiblePosition& b)
     1212{
     1213    return a.isNotNull() && logicalStartOfLine(a) == logicalStartOfLine(b);
     1214}
     1215
     1216VisiblePosition logicalEndOfLine(const VisiblePosition& c)
     1217{
     1218    VisiblePosition visPos = logicalEndPositionForLine(c);
     1219   
     1220    // Make sure the end of line is at the same line as the given input position. For a wrapping line, the logical end
     1221    // position for the not-last-2-lines might incorrectly hand back the logical beginning of the next line.
     1222    // For example, <div contenteditable dir="rtl" style="line-break:before-white-space">abcdefg abcdefg abcdefg
     1223    // a abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg </div>
     1224    // In this case, use the previous position of the computed logical end position.
     1225    if (!inSameLogicalLine(c, visPos))
     1226        visPos = visPos.previous();
     1227   
     1228    return c.honorEditableBoundaryAtOrBefore(visPos);
     1229}
     1230
     1231}
  • trunk/WebCore/editing/visible_units.h

    r43028 r43032  
    5454VisiblePosition nextLinePosition(const VisiblePosition &, int x);
    5555bool inSameLine(const VisiblePosition &, const VisiblePosition &);
     56bool inSameLogicalLine(const VisiblePosition &, const VisiblePosition &);
    5657bool isStartOfLine(const VisiblePosition &);
    5758bool isEndOfLine(const VisiblePosition &);
     59VisiblePosition logicalStartOfLine(const VisiblePosition &);
     60VisiblePosition logicalEndOfLine(const VisiblePosition &);
    5861
    5962// paragraphs (perhaps a misnomer, can be divided by line break elements)
Note: See TracChangeset for help on using the changeset viewer.